home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / other / jikes / src / bytecode.cpp < prev    next >
C/C++ Source or Header  |  1999-05-14  |  219KB  |  5,553 lines

  1. // $Id: bytecode.cpp,v 1.12 1999/03/10 19:59:20 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10.  
  11. #include "assert.h"
  12. #include "config.h"
  13. #include "ast.h"
  14. #include "bytecode.h"
  15. #include "class.h"
  16. #include "control.h"
  17. #include "semantic.h"
  18. #include "stream.h"
  19. #include "symbol.h"
  20. #include "table.h"
  21. #include <iostream.h>
  22. #include <string.h>
  23. #ifndef __amigaos__
  24. #include <wchar.h>
  25. #endif
  26.  
  27. #ifdef WIN32_FILE_SYSTEM
  28. #include <windows.h>
  29. #endif
  30.  
  31.  
  32.  
  33. /*
  34. TODO:
  35.  see if actually need call to ChangeStack, marked CHECK_THIS, in AssigmnentExpression
  36.  */
  37.  
  38.  
  39. void ByteCode::CompileClass(TypeSymbol * type)
  40. {
  41.     AstClassDeclaration * class_decl = type -> declaration -> ClassDeclarationCast();
  42.     AstClassBody * class_body = (class_decl ? class_decl -> class_body :
  43.                                   ((AstClassInstanceCreationExpression *) type -> declaration) -> class_body_opt);;
  44.     int i;
  45.     int mi,pi;
  46.     AstConstructorDeclaration *constructor;
  47.     AstMethodDeclaration *method;
  48.     int super_init=0;
  49.     u2 name;
  50.     int descriptor;
  51.     int need_init=0; // see if need to generate <init> method
  52.     int need_clinit=0; // set if need <clinit> method
  53.     Tuple<AstVariableDeclarator *> initialized_fields(type -> NumVariableSymbols()); // fields needing code to initialize
  54.     int method_index;
  55.     AstFieldDeclaration * field_decl;
  56.     AstList * declarators;
  57.     AstList * block_statements;
  58.     int fi;
  59.     int si;
  60.     AstConstructorBlock * constructor_block;
  61.     VariableSymbol * vsym;
  62.     MethodSymbol * msym;
  63.     AstStaticInitializer * static_initializer;
  64.     class_literal_method = type -> outermost_type -> ClassLiteralMethod();
  65.     
  66.     //
  67.     // Make sure there is an entry in the constant pool for all types on which
  68.     // this type depends. This code is necessary because in the case of a dependence
  69.     // on a type from which we only access a static final constant, the constant is
  70.     // inlined and no other information about it is otherwise recorded.
  71.     //
  72.     for (TypeSymbol *parent = (TypeSymbol *) type -> parents -> FirstElement();
  73.          parent;
  74.          parent = (TypeSymbol *) type -> parents -> NextElement())
  75.     {
  76.         RegisterUtf8(parent -> signature);
  77.     }
  78.  
  79.     //
  80.     // Process static variables.
  81.     //
  82.     for (i=0; i < class_body -> NumClassVariables(); i++) {
  83.         field_decl = class_body -> ClassVariable(i);
  84.         for (int vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
  85.             AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);
  86.             vsym = vd -> symbol;
  87.             //
  88.             // We need a static constructor-initializer if we encounter at least one class
  89.             // variable that is declared with an initialization expression that is not a
  90.             // constant expression.
  91.             //
  92.             need_clinit = need_clinit || (vd -> variable_initializer_opt && !(vsym -> ACC_FINAL() && vsym -> initial_value));
  93.             DeclareField(vsym);
  94.         }
  95.     }
  96.     
  97.     // supply needed field declaration for this$0 (if there is one)
  98.     for (pi = 0; pi < type -> NumConstructorParameters(); pi++)
  99.     {
  100.         DeclareField(type -> ConstructorParameter(pi));
  101.     }
  102.  
  103.     //
  104.     // supply needed field declaration for enclosing instances (this$n) if present
  105.     //
  106.     for (pi = 1; pi < type -> NumEnclosingInstances(); pi++)
  107.     {
  108.         DeclareField(type -> EnclosingInstance(pi));
  109.     }
  110.  
  111.     // supply needed field declarations for "class " identifiers (used for X.class literals) if present
  112.     for (int ri = 0; ri < type -> NumClassLiterals(); ri++)
  113.     {
  114.         DeclareField(type -> ClassLiteral(ri));
  115.     }
  116.  
  117.     for (i=0; i < class_body -> NumInstanceVariables(); i++) {
  118.         field_decl  = class_body -> InstanceVariable(i);
  119.         for (int vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
  120.             AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);
  121.             DeclareField(vd -> symbol);
  122.             // must set Constant attribute if initial value
  123.             if (vd -> variable_initializer_opt) { // if initialization needed
  124.                 need_init=1;
  125.                 initialized_fields.Next() = vd;
  126.             }
  127.         }
  128.     }
  129.     // compile method bodies and constructors
  130.     for (i=0; i < class_body -> NumMethods(); i++) {
  131.         method = class_body -> Method(i);
  132.         if (method -> method_symbol){
  133.             method_index = BeginMethod(METHOD_KIND_ORDINARY, method -> method_symbol); // not constructor
  134.             AstBlock *method_block = method -> method_body -> BlockCast();
  135.             if (method_block) // not an abstract method ?
  136.                 (void) EmitStatement(method_block);
  137.             EndMethod(METHOD_KIND_ORDINARY,method_index, method -> method_symbol); // not constructor
  138.         }
  139.     }
  140.  
  141.     //
  142.     // NOTE that an abstract class that requires this patch may become out-of-date
  143.     // and cause spurious messages to be emitted if any abstract method inherited
  144.     // from an interface is later removed from that interface.
  145.     //
  146.     if (type -> ACC_ABSTRACT())
  147.     {
  148.         for (int i = 0; i < type -> expanded_method_table -> symbol_pool.Length(); i++)
  149.         {
  150.             MethodShadowSymbol *method_shadow_symbol = type -> expanded_method_table -> symbol_pool[i];
  151.             MethodSymbol *method_symbol = method_shadow_symbol -> method_symbol;
  152.             if (method_symbol -> ACC_ABSTRACT() &&
  153.                 method_symbol -> containing_type != type &&
  154.                 method_symbol -> containing_type -> ACC_INTERFACE())
  155.             {
  156.                 if (! method_symbol -> IsTyped())
  157.                     method_symbol -> ProcessMethodSignature(&this_semantic, class_decl -> identifier_token);
  158.                 method_symbol -> ProcessMethodThrows(&this_semantic, class_decl -> identifier_token);
  159.     
  160.                 method_index = BeginMethod(METHOD_KIND_ORDINARY, method_symbol);
  161.                 EndMethod(METHOD_KIND_ORDINARY,method_index, method_symbol);
  162.             }
  163.         }
  164.     }
  165.  
  166. // compile any private access methods
  167.     for (i = 0; i < type -> NumPrivateAccessMethods(); i++) {
  168.         MethodSymbol * method_sym = type -> PrivateAccessMethod(i);
  169. //      AstMethodDeclaration * method_decl = method_sym -> method_or_constructor_declaration -> MethodDeclarationCast();
  170.         method_index = BeginMethod(METHOD_KIND_ACCESS, method_sym);
  171.         GenerateAccessMethod(method_sym);
  172.         EndMethod(METHOD_KIND_ACCESS,method_index, method_sym);
  173.     }
  174.  
  175.     if (type -> ClassLiteralMethod()) {
  176.         MethodSymbol * class_literal_sym = type -> ClassLiteralMethod();
  177.         // generate the class$ identity method used for class literal-related garbage mumbo-jumbo initialization
  178.         method_index = BeginMethod(METHOD_KIND_ACCESS_CLASS, class_literal_sym);
  179.         GenerateClassAccessMethod(class_literal_sym);
  180.         EndMethod(METHOD_KIND_ACCESS_CLASS,method_index, class_literal_sym);
  181.     }
  182.  
  183.     if (type -> block_initializer_method) {
  184.         MethodSymbol * block_init_method = type -> block_initializer_method;
  185.         method_index = BeginMethod(METHOD_KIND_ORDINARY, block_init_method);
  186.                 int fi=0, bi=0;
  187.                 while (fi < initialized_fields.Length() && bi < class_body -> NumBlocks()) {
  188.                     if (initialized_fields[fi] -> LeftToken() < class_body -> Block(bi) -> left_brace_token) {
  189.                         InitializeInstanceVariable(initialized_fields[fi++]);
  190.                     }
  191.                     else {
  192.                         (void) EmitStatement((AstStatement *) (class_body -> Block(bi++)));
  193.                     }
  194.                 }
  195.                         
  196.                 while (fi<initialized_fields.Length()) {
  197.                     InitializeInstanceVariable(initialized_fields[fi++]);
  198.                 }
  199.     
  200.                 // compile any initialization blocks
  201.                 
  202.                 while (bi < class_body -> NumBlocks()) {
  203.                     (void) EmitStatement((AstStatement *) (class_body -> Block(bi++)));
  204.                 }
  205.         
  206.     PutOp(OP_RETURN);
  207.         EndMethod(METHOD_KIND_ORDINARY,method_index,block_init_method);  // is constructor
  208.     }
  209.     
  210.     if (type -> NumGeneratedConstructors() == 0) {
  211.         if (class_body -> default_constructor) {
  212.             CompileConstructor(class_body -> default_constructor, initialized_fields);
  213.         }
  214.         else {
  215.             for (i=0; i < class_body -> NumConstructors(); i++) {
  216.                 constructor = class_body -> Constructor(i);
  217.                 CompileConstructor(constructor, initialized_fields);
  218.             }
  219.             for (i = 0; i < type -> NumPrivateAccessConstructors(); i++) {
  220.                 MethodSymbol *constructor_sym = type -> PrivateAccessConstructor(i);
  221.                 AstConstructorDeclaration *constructor =
  222.                        constructor_sym -> method_or_constructor_declaration -> ConstructorDeclarationCast();
  223.                 CompileConstructor(constructor, initialized_fields);
  224.             }
  225.         }
  226.     }
  227.     else {
  228.         for (i=0; i < type -> NumGeneratedConstructors(); i++) {
  229.             MethodSymbol * this_constructor_symbol = type -> GeneratedConstructor(i);
  230.             AstConstructorDeclaration * constructor =
  231.                     this_constructor_symbol -> method_or_constructor_declaration -> ConstructorDeclarationCast();
  232.             constructor_block = constructor -> constructor_body -> ConstructorBlockCast();
  233.             // compile generated constructor
  234.             method_index = BeginMethod(METHOD_KIND_CONSTRUCTOR, this_constructor_symbol);  // is constructor
  235.             methods[method_index].name_index = RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_));
  236.  
  237.             UpdateBlockInfo(this_constructor_symbol -> block_symbol);
  238.                 
  239.             if (! constructor_block -> explicit_constructor_invocation_opt) {
  240.                 PutOp(OP_ALOAD_0);
  241.                 PutOp(OP_INVOKENONVIRTUAL);   // no args, hence no need to call ChangeStack()
  242.                 PutU2(BuildMethodref(super_class,
  243.                     BuildNameAndType(RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_)), RegisterUtf8(U8S_LP_RP_V, strlen(U8S_LP_RP_V)))));
  244.             }
  245.             else {
  246.                 (void) EmitStatement((AstStatement *) constructor_block -> explicit_constructor_invocation_opt);
  247.             }
  248.  
  249.             for (si = 0;si < constructor_block -> NumLocalInitStatements();si++) {
  250.                 (void) EmitStatement((AstStatement *) constructor_block -> LocalInitStatement(si));
  251.             }
  252.  
  253.             // supply needed field initialization unless constructor
  254.             // starts with explicit 'this' call to another constructor
  255.             if (! (constructor_block -> explicit_constructor_invocation_opt &&
  256.                    constructor_block -> explicit_constructor_invocation_opt -> ThisCallCast())) {
  257.                 if (type -> NumEnclosingInstances()) {
  258.                     VariableSymbol * this0_parameter = type -> EnclosingInstance(0);
  259.                     PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
  260.                     LoadLocal(1, this0_parameter -> Type());
  261.                     PutOp(OP_PUTFIELD);
  262.                     PutU2(GenerateFieldReference(this0_parameter));
  263.                 }
  264.  
  265.                 if (class_body -> this_block) { // compile explicit 'this' call if present
  266.                     AstBlock * block = (AstBlock *) class_body -> this_block;
  267.                     for (si = 0;si < block -> NumStatements();si++) {
  268.                         (void) EmitStatement((AstStatement *) block -> Statement(si));
  269.                     }
  270.                 }
  271.                 
  272.                 if (! type -> block_initializer_method) {
  273.                     int fi=0,bi=0;
  274.                     while (fi < initialized_fields.Length() && bi < class_body -> NumBlocks()) {
  275.                         if (initialized_fields[fi] -> LeftToken() < class_body -> Block(bi) -> left_brace_token) {
  276.                             InitializeInstanceVariable(initialized_fields[fi++]);
  277.                         }
  278.                         else {
  279.                             AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
  280.                             for (si = 0;si < block -> NumStatements();si++) {
  281.                                (void) EmitStatement((AstStatement *) block -> Statement(si));
  282.                             }
  283.                         }
  284.                     }
  285.                         
  286.                     while (fi<initialized_fields.Length()) {
  287.                         InitializeInstanceVariable(initialized_fields[fi++]);
  288.                     }
  289.                     // compile any initialization blocks
  290.                     while (bi < class_body -> NumBlocks()) {
  291.                         AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
  292.                         for (si = 0;si < block -> NumStatements();si++) {
  293.                            (void) EmitStatement((AstStatement *) block -> Statement(si));
  294.                         }
  295.                     }
  296.                 }
  297.                 else {
  298.                     // generate a call to the parameterless function block_initializer_function
  299.                     PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
  300.                     PutOp(OP_INVOKENONVIRTUAL);  
  301.                     CompleteCall(type -> block_initializer_method, 0, 0);
  302.                 }
  303.             }
  304.  
  305.             (void) EmitStatement(constructor_block -> original_constructor_invocation);
  306.             PutOp(OP_RETURN);
  307.             EndMethod(METHOD_KIND_CONSTRUCTOR,method_index, this_constructor_symbol);  // is constructor
  308.  
  309.             // compile method associated with generated constructor
  310.             MethodSymbol * local_constructor_symbol = this_constructor_symbol -> LocalConstructor();
  311.             method_index = BeginMethod(METHOD_KIND_CONSTRUCTOR, local_constructor_symbol);  // is constructor
  312.             methods[method_index].name_index =
  313.                     RegisterUtf8(local_constructor_symbol -> ExternalIdentity() -> Utf8_literal);
  314.  
  315.             for (si = 0;si < constructor_block -> block -> NumStatements();si++) {
  316.                 (void) EmitStatement((AstStatement *) constructor_block -> block -> Statement(si));
  317.             }
  318.             EndMethod(METHOD_KIND_CONSTRUCTOR,method_index,local_constructor_symbol);  // is constructor
  319.         }
  320.     }
  321.     
  322.  
  323.     if (class_body -> NumStaticInitializers() > 0 || need_clinit) {
  324.         msym = type -> static_initializer_method;
  325.         method_index =  BeginMethod(METHOD_KIND_GENERATED_CONSTRUCTOR, msym);
  326.         code_attribute -> max_locals = 0;
  327. // revisit members that are part of class initialization
  328.         for (mi = 0; mi < class_body -> NumClassBodyDeclarations(); mi++) {
  329.             static_initializer = class_body -> ClassBodyDeclaration(mi) -> StaticInitializerCast();
  330.             if (static_initializer) {
  331.                 (void) EmitStatement((AstStatement *) static_initializer -> block);
  332.             }
  333.             else if (class_body -> ClassBodyDeclaration(mi) -> FieldDeclarationCast()) {
  334.                 field_decl = class_body -> ClassBodyDeclaration(mi) -> FieldDeclarationCast();
  335.                 // field declaration
  336.                 for (int vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
  337.                     AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);;
  338.                     vsym = vd -> symbol;
  339.                     if (!vsym -> ACC_STATIC()) continue; // skip non-static fields
  340.                     InitializeClassVariable(vd);
  341.                 }
  342.             }
  343.         }
  344.         PutOp(OP_RETURN);
  345.         EndMethod(METHOD_KIND_GENERATED_CONSTRUCTOR,method_index,msym);
  346.     }
  347.     FinishCode(type);
  348.  
  349.     Write();
  350.  
  351. #ifdef TEST
  352.     if (this_control.option.debug_dump_class) PrintCode();
  353. #endif
  354. }
  355.  
  356. //
  357. // initialized_fields is a list of fields needing code to initialize.
  358. //
  359. void ByteCode::CompileConstructor(AstConstructorDeclaration * constructor, Tuple<AstVariableDeclarator *> &initialized_fields)
  360. {
  361.     
  362.     MethodSymbol * method_symbol = constructor -> constructor_symbol;
  363.     TypeSymbol * type = method_symbol -> containing_type;
  364.     AstClassDeclaration * class_decl = type -> declaration -> ClassDeclarationCast();
  365.     AstClassBody * class_body = (class_decl ? class_decl -> class_body :
  366.                                   ((AstClassInstanceCreationExpression *) type -> declaration) -> class_body_opt);;
  367.     AstBlock * block;
  368.     int is_this=0; // set if start with this() call.
  369.     
  370.     int method_index;
  371.     int fi;
  372.     int si;
  373.     int descriptor;
  374.     AstConstructorBlock * constructor_block;
  375.     AstList * block_statements;
  376.  
  377.     method_index = BeginMethod(METHOD_KIND_CONSTRUCTOR, method_symbol);  // is constructor
  378.     methods[method_index].name_index = RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_));
  379.  
  380.     UpdateBlockInfo(method_symbol -> block_symbol);
  381.  
  382.     constructor_block = constructor -> constructor_body -> ConstructorBlockCast();
  383.     
  384.     if (! constructor_block -> explicit_constructor_invocation_opt) {
  385.     if (super_class) {
  386.             PutOp(OP_ALOAD_0);
  387.             PutOp(OP_INVOKENONVIRTUAL);   // no args, hence no need to call ChangeStack()
  388.             PutU2(BuildMethodref(super_class,
  389.                 BuildNameAndType(RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_)), RegisterUtf8(U8S_LP_RP_V, strlen(U8S_LP_RP_V)))));
  390.     }
  391.     }
  392.     else {
  393.         if (constructor_block -> explicit_constructor_invocation_opt -> ThisCallCast()) is_this=1;
  394.         (void) EmitStatement((AstStatement *) constructor_block -> explicit_constructor_invocation_opt);
  395.     }
  396.  
  397.     // supply needed field initialization unless constructor
  398.     // starts with explicit 'this' call to another constructor
  399.     if (!is_this) {
  400.         if (type -> NumEnclosingInstances()) {
  401.             VariableSymbol * this0_parameter = type -> EnclosingInstance(0);
  402.             PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
  403.             LoadLocal(1, this0_parameter -> Type());
  404.             PutOp(OP_PUTFIELD);
  405.             PutU2(GenerateFieldReference(this0_parameter));
  406.         }
  407.  
  408.         if (class_body -> this_block) { // compile explicit 'this' call if present
  409.             block = (AstBlock *) class_body -> this_block;
  410.             for (si = 0;si < block -> NumStatements();si++) {
  411.                 (void) EmitStatement((AstStatement *)block -> Statement(si));
  412.             }
  413.         }
  414.         if (!type -> block_initializer_method) {
  415.         int fi=0,bi=0;
  416.         while (fi < initialized_fields.Length() && bi < class_body -> NumBlocks()) {
  417.             if (initialized_fields[fi] -> LeftToken() < class_body -> Block(bi) -> left_brace_token) {
  418.                 InitializeInstanceVariable(initialized_fields[fi++]);
  419.             }
  420.             else {
  421.                 AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
  422.                 for (si = 0;si < block -> NumStatements();si++) {
  423.                    (void) EmitStatement((AstStatement *) block -> Statement(si));
  424.                 }
  425.  
  426.             }
  427.         }
  428.                 
  429.         while (fi<initialized_fields.Length()) {
  430.             InitializeInstanceVariable(initialized_fields[fi++]);
  431.         }
  432.     
  433.         // compile any initialization blocks
  434.         
  435.         while (bi < class_body -> NumBlocks()) {
  436.             AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
  437.             for (si = 0;si < block -> NumStatements();si++) {
  438.                (void) EmitStatement((AstStatement *) block -> Statement(si));
  439.             }
  440.         }
  441.         }
  442.         else {
  443.             // generate a call to the parameterless function block_initializer_function
  444.             PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
  445.             PutOp(OP_INVOKENONVIRTUAL);  
  446.             CompleteCall(type -> block_initializer_method, 0, 0);
  447.         }
  448.  
  449.     }
  450.     
  451.  
  452.     (void) EmitStatement(constructor_block -> block);
  453.  
  454.     EndMethod(METHOD_KIND_CONSTRUCTOR,method_index, method_symbol);
  455. }
  456.  
  457.  
  458. void ByteCode::CompileInterface(TypeSymbol * type)
  459. {
  460.     AstInterfaceDeclaration * interface_decl = type -> declaration -> InterfaceDeclarationCast();
  461.     AstMethodDeclaration * method;
  462.     int method_index;
  463.     int i;
  464.     int vi;
  465.     int need_clinit=0; // set if need <clinit> method
  466.     VariableSymbol * vsym;
  467.     AstFieldDeclaration * field_decl;
  468.     AstVariableDeclarator * vd;
  469.     u2 name;
  470.     AstList * declarators;
  471.     for (i=0; i < interface_decl -> NumClassVariables(); i++) {
  472.         field_decl  = interface_decl -> ClassVariable(i);
  473.  
  474.         for (vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
  475.             AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);
  476.             vsym = vd -> symbol;
  477.             //
  478.             // We need a static constructor-initializer if we encounter at least one class
  479.             // variable that is declared with an initialization expression that is not a
  480.             // constant expression.
  481.             //
  482.             need_clinit = need_clinit || (vd -> variable_initializer_opt && !(vsym -> ACC_FINAL() && vsym -> initial_value));
  483.             DeclareField(vsym);
  484.         }
  485.     }
  486.  
  487.     for (i=0; i < interface_decl -> NumMethods(); i++) {
  488.  
  489.         method = interface_decl -> Method(i);
  490.         if (method  ->  method_symbol){
  491.             method_index = BeginMethod(METHOD_KIND_INTERFACE, method -> method_symbol); // not constructor
  492.             EndMethod(METHOD_KIND_INTERFACE,method_index, method -> method_symbol);
  493.         }
  494.     }
  495.  
  496.     if (need_clinit) {
  497.         method_index =  BeginMethod(METHOD_KIND_GENERATED_CONSTRUCTOR, (MethodSymbol *) 0);
  498.         code_attribute -> max_locals = 0;
  499.         methods[method_index].SetACC_FINAL();
  500.         // revisit members that are part of class initialization
  501.         for (int mi = 0; mi < interface_decl -> NumClassVariables(); mi++) {
  502.                 // field declaration
  503.                 field_decl = interface_decl -> ClassVariable(mi);
  504.                 for (int vi2=0;vi2<field_decl -> NumVariableDeclarators();vi2++) {
  505.                     vd = field_decl -> VariableDeclarator(vi2);
  506.                     vsym = vd -> symbol;
  507.                     if (!vsym -> ACC_STATIC()) continue; // skip non-static fields
  508.                     InitializeClassVariable(vd);
  509.             }
  510.         }
  511.         PutOp(OP_RETURN);
  512.         EndMethod(METHOD_KIND_GENERATED_CONSTRUCTOR,method_index, (MethodSymbol *)0);
  513.     }
  514.     FinishCode(type);
  515.  
  516.     Write();
  517.  
  518. #ifdef TEST
  519.     if (this_control.option.debug_dump_class) PrintCode();
  520. #endif
  521.  
  522. }
  523.  
  524. void ByteCode::DeclareField(VariableSymbol * symbol)
  525. {
  526.     int field_index = fields.NextIndex(); // index for field
  527.  
  528.     fields[field_index].access_flags = symbol -> access_flags;
  529.     fields[field_index].name_index = RegisterUtf8(symbol -> ExternalIdentity() -> Utf8_literal);
  530.     fields[field_index].descriptor_index = RegisterUtf8(symbol -> Type() -> signature);
  531.  
  532.     TypeSymbol *type = symbol -> Type();
  533.     if (symbol -> ACC_FINAL() && symbol -> initial_value && (type -> Primitive() || type == this_control.String())) {
  534.         u4 constant_value_attribute_length = 2;
  535.         int lit_index = GetConstant(symbol -> initial_value, symbol -> Type());
  536.  
  537.         u2 name = RegisterUtf8(U8S_ConstantValue, strlen(U8S_ConstantValue));
  538.         ConstantValue_attribute *constant_value_attribute = new ConstantValue_attribute(name, constant_value_attribute_length);
  539.  
  540.         constant_value_attribute -> constantvalue_index = lit_index;
  541.         fields[field_index].attributes.Next() = constant_value_attribute;
  542.     }
  543.  
  544.     if (symbol -> IsSynthetic())
  545.     {
  546.         fields[field_index].attributes.Next() = CreateSyntheticAttribute();
  547.     }
  548.  
  549.     return;
  550. }
  551.             
  552. void ByteCode::GenerateAccessMethod(MethodSymbol * method_symbol)
  553. {
  554.     // generate code for access method to private member of containing class
  555.  
  556.     int stack_words = 0;
  557.     int argument_offset = 0; // offset to start of argument
  558.     code_attribute -> max_locals = 1; // DS fix this 01 dec 97
  559.     TypeSymbol * parameter_type;
  560.  
  561.  
  562.     VariableSymbol * field_sym = method_symbol -> accessed_member -> VariableCast();
  563.     // generate code according to type of method
  564.     if (method_symbol -> accessed_member -> MethodCast()) {
  565.         // if accessing another method
  566.         // copy arguments
  567.         if (! method_symbol -> ACC_STATIC()) {
  568.             PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
  569.         }
  570.         for (int i = 0; i < method_symbol -> NumFormalParameters(); i++) {
  571.             TypeSymbol * local_type = method_symbol -> FormalParameter(i) -> Type();
  572.             code_attribute -> max_locals += GetTypeWords(local_type);
  573.             stack_words += GetTypeWords(local_type);
  574.             LoadLocal(method_symbol -> ACC_STATIC() ? argument_offset: argument_offset+1, local_type);
  575.             argument_offset += GetTypeWords(local_type); // update position in stack
  576.         }
  577.         PutOp(method_symbol -> ACC_STATIC() ? OP_INVOKESTATIC  // must be static or private
  578.                                             : OP_INVOKENONVIRTUAL);  
  579.         CompleteCall(method_symbol -> accessed_member -> MethodCast(), stack_words, 0);
  580.     }
  581.     else {
  582.         // accessing field
  583.         if (method_type == this_control.void_type) {
  584.             // need method to assign value to field
  585.             if (method_symbol -> NumFormalParameters()== 0) {
  586.                 chaos("assignment access method requires parameter");
  587.             }  
  588.             parameter_type = method_symbol -> FormalParameter(0) -> Type();
  589.             code_attribute -> max_locals += GetTypeWords(parameter_type);
  590.             
  591.             if (method_symbol -> ACC_STATIC()) {
  592.                 LoadLocal(0, parameter_type);
  593.                 PutOp(OP_PUTSTATIC);
  594.             }
  595.             else {
  596.                 PutOp(OP_ALOAD_0); // get this for field access
  597.                 LoadLocal(1, parameter_type);
  598.                 PutOp(OP_PUTFIELD);
  599.             }
  600.             ChangeStack(this_control.IsDoubleWordType(parameter_type) ? -2: -1);
  601.             PutU2(GenerateFieldReference(method_symbol -> accessed_member -> VariableCast()));
  602.         }
  603.         else {
  604.             // need method to retrieve value of field
  605.             if (field_sym -> ACC_STATIC()) {
  606.                 PutOp(OP_GETSTATIC);
  607.                 ChangeStack(this_control.IsDoubleWordType(method_type) ? 2: 1);
  608.             }
  609.             else {
  610.                 PutOp(OP_ALOAD_0); // get this for field access
  611.                 PutOp(OP_GETFIELD);
  612.                 ChangeStack(this_control.IsDoubleWordType(method_type) ? 1: 0);
  613.             }
  614.             PutU2(GenerateFieldReference(field_sym));
  615.         }
  616.     }
  617.     
  618.         // method returns void, generate return unless last statement is return
  619.     if (method_type == this_control.void_type) {
  620.         //  int line_index;
  621.         // line_index = line_number_table_attribute -> line_number_table.NextIndex();
  622.         // line_number_table_attribute -> line_number_table[line_index]
  623.         PutOp(OP_RETURN);// guarantee return at end of body
  624.     }
  625.     else GenerateReturn(method_type);
  626.     if (last_label_pc >= code_attribute -> code.Length()) {
  627.         // here to emit noop if would otherwise EmitBranch past end
  628.         PutNop(0);
  629.     }
  630. }
  631.  
  632. void ByteCode::GenerateReturn(TypeSymbol * type)
  633. {
  634.     if (this_control.IsSimpleIntegerValueType(type)|| type==this_control.boolean_type) {
  635.         PutOp(OP_IRETURN);
  636.     }
  637.     else if (type==this_control.long_type) {
  638.         PutOp(OP_LRETURN);
  639.     }
  640.     else if (type==this_control.float_type) {
  641.         PutOp(OP_FRETURN);
  642.     }
  643.     else if (type==this_control.double_type) {
  644.         PutOp(OP_DRETURN);
  645.     }
  646.     else  {// must be reference expression
  647.         PutOp(OP_ARETURN);
  648.     }
  649. }
  650.  
  651. int ByteCode::BeginMethod(int method_kind, MethodSymbol * msym) 
  652. {
  653.     // is_constructor is set if this is constructor, is_generated_constructor is set is need to compile
  654.     // default (no argument) constructor.
  655.  
  656.     BlockSymbol * block_symbol;
  657.     TypeSymbol * throw_symbol;
  658.     u4 length_code=0;                   // dummy value, will supply real value after code generated.
  659.     int i;
  660.     u4 line_number_table_attribute_length = 0;
  661.     u4 exceptions_attribute_length = 0;
  662.     u4 local_variable_table_attribute_length = 0;
  663.     stack_depth = 0;
  664.     last_label_pc = 0;
  665.     last_op_pc = 0;
  666.     last_op_nop = 0;
  667.     this_block_depth = 0;
  668.     int method_index = methods.NextIndex(); // index for method
  669.     u2 name;
  670.     switch (method_kind) {
  671.         case METHOD_KIND_ORDINARY:
  672.         case METHOD_KIND_ACCESS:
  673.         case METHOD_KIND_ACCESS_CLASS:
  674.         case METHOD_KIND_INTERFACE:
  675.             methods[method_index].name_index = RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal);
  676.             methods[method_index].descriptor_index = RegisterUtf8(msym -> signature);
  677.             break;
  678.         case METHOD_KIND_CONSTRUCTOR:
  679.             // caller sets name
  680.             methods[method_index].descriptor_index = RegisterUtf8(msym -> signature);
  681.             break;
  682.     case METHOD_KIND_GENERATED_CONSTRUCTOR:
  683.         methods[method_index].name_index = RegisterUtf8(U8S_LT_clinit_GT_, strlen(U8S_LT_clinit_GT_));
  684.         methods[method_index].descriptor_index = RegisterUtf8(U8S_LP_RP_V, strlen(U8S_LP_RP_V));
  685.         methods[method_index].SetACC_STATIC();
  686.         break;
  687.     }
  688.  
  689.     if (method_kind==METHOD_KIND_CONSTRUCTOR || method_kind == METHOD_KIND_GENERATED_CONSTRUCTOR) {
  690.        method_type = this_control.Object();
  691.        if (msym == (MethodSymbol *) 0)  {
  692.            max_block_depth = 2;
  693.         }
  694.         else {
  695.            max_block_depth = msym -> max_block_depth;
  696.         }
  697.     }
  698.     else { // normal method declaration 
  699.             max_block_depth = msym -> max_block_depth;
  700.         block_symbol = msym -> block_symbol;
  701.         method_type = msym -> Type();
  702.     }
  703.     // set access flags for non-generated constructor. If we have
  704.     // generated the constructore, then the access flags have been
  705.     // set to be the same as those of the containing class.
  706.     if (method_kind != METHOD_KIND_GENERATED_CONSTRUCTOR) {
  707.         methods[method_index].access_flags = msym -> access_flags;
  708.     }
  709. #ifdef MAKE_FINAL_PUBLIC
  710.     if (method_kind==METHOD_KIND_ACCESS) { // DS debug 01 dec 97
  711.       AccessFlags flags;
  712.       flags.access_flags = methods[method_index].access_flags;
  713.       flags.SetACC_PUBLIC();
  714.       flags.SetACC_FINAL();
  715.       methods[method_index].access_flags = flags.access_flags;
  716.      }
  717. #endif
  718.     if (msym)
  719.     {
  720.         if (msym -> IsSynthetic())
  721.         {
  722.             methods[method_index].attributes.Next() = CreateSyntheticAttribute();  
  723.         }
  724.  
  725.         //
  726.         // Generate throws attribute if method throws any exceptions
  727.         //
  728.         if (msym -> NumThrows())
  729.         {
  730.             exceptions_attribute_length = 2 * (1 + msym -> NumThrows());
  731.             name = RegisterUtf8(U8S_Exceptions, strlen(U8S_Exceptions));
  732.             Exceptions_attribute * exceptions_attribute = new Exceptions_attribute(name, exceptions_attribute_length);
  733.             for (int i = 0; i < msym -> NumThrows(); i++)
  734.             {
  735.                 throw_symbol = (TypeSymbol *) msym -> Throws(i);
  736.                 exceptions_attribute -> exception_index_table.Next() = RegisterClass(throw_symbol -> fully_qualified_name);
  737.             }
  738.             methods[method_index].attributes.Next() = exceptions_attribute;
  739.         }
  740.     }
  741.  
  742.     if (method_kind==METHOD_KIND_INTERFACE) return method_index;
  743.     // here if need code and associated attributes.
  744.     if (this_control.option.g) {
  745.         name = RegisterUtf8(U8S_LocalVariableTable, strlen(U8S_LocalVariableTable));
  746.         local_variable_table_attribute= new LocalVariableTable_attribute(name, local_variable_table_attribute_length);
  747.     }
  748.     begin_labels = new Label[max_block_depth + 1];
  749.     break_labels = new Label[max_block_depth + 1];
  750.     continue_labels = new Label[max_block_depth + 1];
  751.     test_labels = new Label[max_block_depth + 1];
  752.     final_labels = new Label[max_block_depth + 1];
  753.     monitor_labels = new Label[max_block_depth + 1];
  754.     has_finally_clause = new int[max_block_depth+1];
  755.     is_synchronized = new int[max_block_depth+1];
  756.     block_symbols = new BlockSymbol *[max_block_depth+1];
  757.     for (i=0;i<max_block_depth;i++) {
  758.         has_finally_clause[i]=0; // reset has_finally_clause
  759.         is_synchronized[i]=0; // reset has_finally_clause
  760.     }
  761.  
  762.     if (! (msym && (msym -> ACC_ABSTRACT() || msym -> ACC_NATIVE())))
  763.     {
  764.         name = RegisterUtf8(U8S_Code, strlen(U8S_Code));
  765.         code_attribute  = new Code_attribute(name,length_code);
  766.         code_attribute -> max_stack = 0;
  767.         code_attribute -> max_locals = 0;
  768.     
  769.         if (method_kind==METHOD_KIND_CONSTRUCTOR || method_kind==METHOD_KIND_GENERATED_CONSTRUCTOR) {
  770.             if (method_kind!=METHOD_KIND_GENERATED_CONSTRUCTOR) {
  771.                 block_symbol = msym -> block_symbol;
  772.                 if (block_symbol && block_symbol -> max_variable_index > code_attribute -> max_locals)
  773.                 {
  774.                     code_attribute -> max_locals = msym -> block_symbol -> max_variable_index;
  775.                 }
  776.             }
  777.         }
  778.         else {
  779.             block_symbol = msym -> block_symbol;
  780.             if(block_symbol && block_symbol -> max_variable_index>code_attribute -> max_locals){
  781.                 code_attribute -> max_locals = block_symbol -> max_variable_index;
  782.             }
  783.         }
  784.         code_attribute -> attribute_name_index = RegisterUtf8(U8S_Code, strlen(U8S_Code));
  785.  
  786.         line_number=0;  // temporary until PC
  787.         name = RegisterUtf8(U8S_LineNumberTable, strlen(U8S_LineNumberTable));
  788.         line_number_table_attribute  = new LineNumberTable_attribute(name, line_number_table_attribute_length);
  789.         line_number_table_attribute -> attribute_name_index = name;
  790.     }
  791.  
  792.     if (msym && msym -> NumFormalParameters()) {
  793.         VariableSymbol * last_sym = (VariableSymbol *) msym -> FormalParameter(msym -> NumFormalParameters() - 1);
  794.         last_parameter_index = last_sym -> LocalVariableIndex();
  795.     }
  796.     else {
  797.         last_parameter_index = -1;
  798.     }
  799.     return method_index;
  800. }
  801.  
  802. void ByteCode::EndMethod(int method_kind,int method_index, MethodSymbol *method_sym) 
  803. {
  804.     int i;
  805.     u4 length_line_number_table_attribute = 0;
  806.     this_block_depth=0;
  807.     TypeSymbol * ptype;
  808.     int has_code = 1; // Assume Code Attribute needed
  809.     if (method_kind==METHOD_KIND_INTERFACE) return;
  810.     if (method_kind==METHOD_KIND_CONSTRUCTOR || method_kind==METHOD_KIND_GENERATED_CONSTRUCTOR) {
  811.         ptype= this_control.void_type;
  812.     }
  813.     else {
  814.         ptype = method_sym -> Type();
  815.         if (method_sym -> ACC_ABSTRACT() || method_sym -> ACC_NATIVE()) has_code =  0;
  816.     }
  817. #ifdef NONO    
  818.     if (has_code && ptype==this_control.void_type) {
  819.         // method returns void, generate return unless last statement is return
  820.             //  int line_index;
  821.             // line_index = line_number_table_attribute -> line_number_table.NextIndex();
  822.             // line_number_table_attribute -> line_number_table[line_index]
  823.            PutOp(OP_RETURN);// guarantee return at end of body
  824.     }
  825. #endif
  826.     if (has_code) {
  827.         if (last_label_pc >= code_attribute -> code.Length()) {
  828.             // here to emit noop if would otherwise branch past end
  829.             PutNop(0);
  830.         }
  831.             
  832.         // attribute length:
  833.         // need to review how to make attribute_name and attribute_length
  834.         // only write line number attribute if -O not specified and there
  835.         // are line numbers to write.
  836.         if (!this_control.option.O && line_number_table_attribute -> line_number_table.Length()) {
  837.             line_number_table_attribute -> attribute_length = 
  838.                 line_number_table_attribute -> line_number_table.Length()*4 + 2;
  839.             code_attribute -> attributes.Next() = line_number_table_attribute;
  840.         }
  841.         else { // line_number_table_attribute not needed, so delete it now
  842.           delete line_number_table_attribute;
  843.         }
  844.         if (this_control.option.g) {
  845.             if (method_kind==METHOD_KIND_ORDINARY) {
  846.                 if (! method_sym -> ACC_STATIC()) {
  847.                     // add 'this' to local variable table
  848.                     AddLocalVariableTableEntry(0, code_attribute -> code.Length(), RegisterUtf8(U8S_this, strlen(U8S_this)),
  849.                         RegisterUtf8(method_sym -> containing_type -> signature), 0);
  850.                 }
  851.             }
  852.             else if (method_kind==METHOD_KIND_CONSTRUCTOR && method_sym) {
  853.                 AddLocalVariableTableEntry(0, code_attribute -> code.Length(), RegisterUtf8(U8S_this, strlen(U8S_this)),
  854.                     RegisterUtf8(method_sym -> containing_type -> signature), 0);
  855.             }
  856.             if (method_kind==METHOD_KIND_ORDINARY || method_kind == METHOD_KIND_CONSTRUCTOR) {
  857.                 for (i = 0; i < method_sym -> NumFormalParameters(); i++) {
  858.                    VariableSymbol * parameter = method_sym -> FormalParameter(i);
  859.                    AddLocalVariableTableEntry(0, code_attribute -> code.Length(),
  860.                    RegisterUtf8(parameter -> ExternalIdentity() -> Utf8_literal),
  861.                    RegisterUtf8(parameter -> Type() -> signature),
  862.                    parameter -> LocalVariableIndex());
  863.                 }
  864.             }
  865.             if (local_variable_table_attribute -> local_variable_table.Length()) {
  866.                 local_variable_table_attribute -> attribute_length = 
  867.                 local_variable_table_attribute -> local_variable_table.Length()*10 + 2;
  868.                 code_attribute -> attributes.Next() = local_variable_table_attribute;
  869.             }
  870.         }
  871.          // std. fields of attribute_info
  872.         int attribute_info_length = 0;
  873.         for (i = 0; i < code_attribute -> attributes.Length(); i++) {
  874.             if (code_attribute -> attributes[i] -> attribute_length) attribute_info_length += (code_attribute -> attributes[i] -> attribute_length+6);
  875.         }
  876.         code_attribute -> attribute_length = + 2 // for max_stack
  877.                + 2  // for max_locals
  878.                + 4      // for code_length
  879.                + code_attribute -> code.Length() // for code
  880.                + 2  // for exception_table_length
  881.                + code_attribute -> exception_table.Length() * 8  // for exception table
  882.                + 2  // for attributes_count
  883.                + attribute_info_length
  884.               ;
  885.     
  886.         methods[method_index].attributes.Next() = code_attribute;
  887.     }
  888.     delete [] begin_labels;
  889.     delete [] break_labels;
  890.     delete [] continue_labels;
  891.     delete [] final_labels;
  892.     delete [] monitor_labels;
  893.     delete [] test_labels;
  894.  
  895.     delete [] has_finally_clause;
  896.     delete [] is_synchronized;
  897.     delete [] block_symbols;
  898.         
  899. }
  900.  
  901.  
  902. void ByteCode::InitializeClassVariable(AstVariableDeclarator * vd)
  903. {
  904.     VariableSymbol * symbol = vd -> symbol;
  905.     AstExpression * expression;
  906.     TypeSymbol * expression_type;
  907.     if (vd -> variable_initializer_opt) { // field needs initialization
  908.         expression = (AstExpression *) vd -> variable_initializer_opt;
  909.         if (expression -> ArrayInitializerCast()) {
  910.             InitializeArray(vd -> symbol ->Type(),
  911.                     expression -> ArrayInitializerCast());
  912.         }
  913.         else if (symbol -> ACC_FINAL() && expression -> IsConstant()) return; // if already initialized
  914.         else if (!initialize_statics_in_clinit && expression -> IsConstant()) return; // if already initialized
  915.         else {
  916.             expression_type = expression -> Type();
  917.             EmitExpression(expression);
  918.         }
  919.         PutOp(OP_PUTSTATIC);
  920.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
  921.         PutU2(GenerateFieldReference(symbol));
  922.     }
  923. }
  924.  
  925. void ByteCode::InitializeInstanceVariable(AstVariableDeclarator * vd)
  926. {
  927.     VariableSymbol * symbol = vd -> symbol;
  928.     TypeSymbol * type = symbol -> Type();
  929.     AstExpression * expression;
  930.     TypeSymbol * expression_type;
  931.     if (vd -> variable_initializer_opt) { // field needs initialization
  932.         expression = (AstExpression *) vd -> variable_initializer_opt;
  933.         if (expression -> ArrayInitializerCast()) {
  934.             PutOp(OP_ALOAD_0); // load 'this'
  935.             InitializeArray(vd -> symbol ->Type(),
  936.                     expression -> ArrayInitializerCast());
  937.         }
  938.         else {
  939.             expression_type = expression -> Type();
  940.             PutOp(OP_ALOAD_0); // load 'this'
  941.             EmitExpression(expression);
  942.         }
  943.         PutOp(OP_PUTFIELD);
  944.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
  945.         PutU2(GenerateFieldReference(symbol));
  946.     }
  947. }
  948.  
  949. void ByteCode::InitializeArray(TypeSymbol *type, AstArrayInitializer * array_initializer)
  950. {
  951.     int i;
  952.     AstExpression * expr;
  953.     Ast * entry;
  954.     TypeSymbol * subtype = type -> ArraySubtype();  
  955.     int num_ent = array_initializer -> NumVariableInitializers();
  956.  
  957.     LoadInteger(num_ent);
  958.     EmitNewArray(1,type); // make the array
  959.     for (i=0;i<num_ent;i++) {
  960.         entry =  array_initializer -> VariableInitializer(i);
  961.         PutOp(OP_DUP);
  962.         LoadInteger(i);
  963.         expr=entry -> ExpressionCast();
  964.         if (expr) {
  965.             EmitExpression(expr);
  966.         }
  967.         else if (entry -> ArrayInitializerCast()) {
  968.           InitializeArray(subtype, entry -> ArrayInitializerCast());
  969.         }
  970.         else chaos("wrong array initializer list element type");
  971.       
  972.         StoreArrayElement(subtype);
  973.     }
  974. }     
  975.  
  976. void ByteCode::DeclareLocalVariable(AstVariableDeclarator * declarator)
  977. {
  978.     AstArrayCreationExpression * ace;
  979.     // generate code for local variable declaration.
  980.     if (this_control.option.g) {
  981.         declarator -> symbol -> local_program_counter = code_attribute -> code.Length();
  982.     }
  983.     if (declarator -> symbol -> initial_value) {
  984.         (void) LoadLiteral(declarator -> symbol -> initial_value,declarator -> symbol -> Type()); // Is LiteralValue *
  985.     }
  986.     else if (declarator -> variable_initializer_opt) {
  987.         ace = declarator -> variable_initializer_opt -> ArrayCreationExpressionCast();
  988.         if (ace) {
  989.             (void) EmitArrayCreationExpression(ace);
  990.         }
  991.         else if (declarator -> variable_initializer_opt -> ArrayInitializerCast()) {
  992.             InitializeArray(declarator -> symbol ->Type(),
  993.                             declarator -> variable_initializer_opt -> ArrayInitializerCast());
  994.         }
  995.         else { // evaluation as expression
  996.             EmitExpression(declarator -> variable_initializer_opt -> ExpressionCast());
  997.         }
  998.     }
  999.     else return; // if nothing to initialize
  1000.  
  1001.     StoreLocalVariable(declarator -> symbol);
  1002. }
  1003.  
  1004. // JLS Chapter 13: Blocks and Statements
  1005. //  Statements control the sequence of evaluation of Java programs,
  1006. //  are executed for their effects and do not have values.
  1007. //
  1008. // Processing of loops requires a loop stack, especially to hangle
  1009. // break and continue statements.
  1010. // Loops have three labels, LABEL_BEGIN for start of loop body,
  1011. // LABEL_BREAK to leave the loop, and LABEL_CONTINUE to continue the iteration.
  1012. // Each loop requires a break label; other labels are defined and used
  1013. // as needed.
  1014. // Labels allocated but never used incur no extra cost in the generated
  1015. // byte code, only in additional execution expense during compilation.
  1016.  
  1017. int ByteCode::EmitStatement(AstStatement *statement) 
  1018. {
  1019.     // generate code for statement (JLS 13.4). The list of statement kinds
  1020.     // are those used in grammar, not precisely those used in JLS..
  1021.     // return 1 if execution of statement causes abrupt exit, 0 otherwise.
  1022.  
  1023.     LexStream::TokenIndex start;
  1024.     int abrupt = 0;
  1025.     if (statement -> kind !=Ast::BLOCK) {
  1026.         int line_number_index = line_number_table_attribute -> line_number_table.NextIndex();
  1027.         start = statement -> LeftToken();
  1028.         line_number_table_attribute -> line_number_table[line_number_index].line_number =
  1029.             this_semantic.lex_stream -> Line(start);
  1030.         line_number_table_attribute -> line_number_table[line_number_index].start_pc =
  1031.             code_attribute -> code.Length(); // pc at start of statement
  1032.     }
  1033.     stack_depth = 0; // stack empty at start of statement
  1034.  
  1035.     switch (statement -> kind) {
  1036.         case Ast::BLOCK:                        // JLS 13.2
  1037.             return EmitBlockStatement((AstBlock *) statement, 0);
  1038.             
  1039.         case Ast::LOCAL_VARIABLE_DECLARATION:// JLS 13.3
  1040.             {
  1041.             // generate code for local variable declaration.
  1042.                 AstLocalVariableDeclarationStatement * lvds = statement -> LocalVariableDeclarationStatementCast();
  1043.                 for (int i=0; i<lvds -> NumVariableDeclarators();i++) {
  1044.                     DeclareLocalVariable(lvds -> VariableDeclarator(i));
  1045.                 }
  1046.             }
  1047.             break;
  1048.         case Ast::EMPTY_STATEMENT:          // JLS 13.5
  1049.             break;
  1050.         case Ast::EXPRESSION_STATEMENT:     // JLS 13.7
  1051.             EmitStatementExpression(statement -> ExpressionStatementCast() -> expression);
  1052.             break;
  1053.         case Ast::IF:                       // JLS 13.8
  1054.                 {
  1055.             AstIfStatement * ifStatement = (AstIfStatement *) statement;
  1056.             if (ifStatement -> expression -> IsConstant()) {
  1057.                 IntLiteralValue *if_constant_expr = (IntLiteralValue *) ifStatement -> expression -> value;
  1058.                 // Open question (DS, 20 Jan 97): Should be we setting abrupt here? If we weren't
  1059.                 // doing this optimization, then we wouldn't be setting abrupt. Note that if expression
  1060.                 // is, for example, non-zero and then-block terminates abruptly, then the following
  1061.                 // statement is unreachable.
  1062.                 if (if_constant_expr -> value)
  1063.                      EmitStatement(ifStatement -> true_statement);
  1064.                 else if (ifStatement -> false_statement_opt) // if there is false part
  1065.                      EmitStatement(ifStatement -> false_statement_opt);
  1066.             }
  1067.             else {
  1068.                 if (ifStatement -> false_statement_opt) {   // if true and false parts
  1069.                     Label  label1;
  1070.                     Label  label2;
  1071.                     int true_abrupt; // set if last statement in true block is abrupt exit
  1072.                     int false_abrupt; // set if last statement in false block is abrupt exit
  1073.     
  1074.                     EmitBranchIfExpression(ifStatement -> expression, false, label1);
  1075.                     stack_depth = 0;
  1076.                     true_abrupt = EmitStatement(ifStatement -> true_statement);
  1077.                     if (!true_abrupt) {
  1078.                         EmitBranch(OP_GOTO,label2);
  1079.                     }
  1080.                     DefineLabel(label1);
  1081.                     false_abrupt =  EmitStatement(ifStatement -> false_statement_opt);
  1082.                     if (!true_abrupt) {
  1083.                         DefineLabel(label2);
  1084.                     }
  1085.                     CompleteLabel(label1);
  1086.                     CompleteLabel(label2);
  1087.                     // if terminates abruptly only if both clauses terminate abruptly
  1088.                     abrupt =  true_abrupt ? false_abrupt : 0;
  1089.                 }
  1090.                 else { // if no false part
  1091.                     Label label1;
  1092.                     EmitBranchIfExpression(ifStatement -> expression, false, label1);
  1093.                     stack_depth=0;
  1094.                     (void) EmitStatement(ifStatement -> true_statement);
  1095.                     DefineLabel(label1);
  1096.                     CompleteLabel(label1);
  1097.                 }
  1098.             }
  1099.                 }
  1100.         break;
  1101.         case Ast::SWITCH:                   // JLS 13.9
  1102.  
  1103.                 EmitSwitchStatement(statement -> SwitchStatementCast());
  1104.         break;
  1105.         case Ast::SWITCH_BLOCK:             // JLS 13.9
  1106.         case Ast::CASE:                     // JLS 13.9
  1107.         case Ast::DEFAULT:                  // JLS 13.9
  1108.             // these nodes handled by SwitchStatement and
  1109.             // are not directly visited
  1110.             break;
  1111.         case Ast::WHILE:
  1112.                 {               // JLS 13.10
  1113.             AstWhileStatement * wp = statement -> WhileStatementCast();
  1114.             // branch to continuation test. This test is placed after the
  1115.             // body of the loop we can fall through into it after each
  1116.             // loop iteration without the need for an additional branch.
  1117.             int while_depth = this_block_depth;
  1118.             EmitBranch(OP_GOTO,continue_labels[while_depth]);
  1119.             DefineLabel(begin_labels[while_depth]);
  1120.             (void) EmitStatement(wp -> statement);
  1121.             DefineLabel(continue_labels[while_depth]);
  1122.             stack_depth=0;
  1123.             EmitBranchIfExpression(wp -> expression,true,
  1124.                                  begin_labels[while_depth]);
  1125.             CompleteLabel(begin_labels[while_depth]);
  1126.             CompleteLabel(continue_labels[while_depth]);
  1127.                 }
  1128.             break;
  1129.         case Ast::DO:                       // JLS 13.11
  1130.                 {
  1131.             AstDoStatement * sp = statement -> DoStatementCast();
  1132.             int do_depth=this_block_depth;
  1133.             DefineLabel(begin_labels[do_depth]);
  1134.             (void) EmitStatement(sp -> statement);
  1135.             DefineLabel(continue_labels[do_depth]);
  1136.             stack_depth=0;
  1137.             EmitBranchIfExpression(sp -> expression,true,
  1138.                                  begin_labels[do_depth]);
  1139.             CompleteLabel(begin_labels[do_depth]);
  1140.             CompleteLabel(continue_labels[do_depth]);
  1141.                 }
  1142.  
  1143.             break;
  1144.         case Ast::FOR:                      // JLS 13.12
  1145.                 {
  1146.             int i;
  1147.             int for_depth;
  1148.             AstForStatement * forStatement = statement -> ForStatementCast();
  1149.             for_depth=this_block_depth;
  1150.             for (i=0; i<forStatement -> NumForInitStatements();i++) {
  1151.                 EmitStatement((AstStatement *) forStatement -> ForInitStatement(i));
  1152.             }
  1153.             EmitBranch(OP_GOTO,test_labels[for_depth]);
  1154.             DefineLabel(begin_labels[for_depth]);
  1155.             (void) EmitStatement(forStatement -> statement);
  1156.             DefineLabel(continue_labels[for_depth]);
  1157.             for (i=0; i<forStatement -> NumForUpdateStatements();i++) {
  1158.                 (void) EmitStatement((AstStatement *) forStatement -> ForUpdateStatement(i));
  1159.             }
  1160.             DefineLabel(test_labels[for_depth]);
  1161.             if (forStatement -> end_expression_opt) {
  1162.                 stack_depth=0;
  1163.                 EmitBranchIfExpression(forStatement -> end_expression_opt,true,
  1164.                                      begin_labels[for_depth]);
  1165.             }
  1166.             else  {
  1167.                 EmitBranch(OP_GOTO,begin_labels[for_depth]);
  1168.             }
  1169.             CompleteLabel(begin_labels[for_depth]);
  1170.             CompleteLabel(test_labels[for_depth]);
  1171.             CompleteLabel(continue_labels[for_depth]);
  1172.                 }
  1173.             break;
  1174.         case Ast::BREAK:                        // JLS 13.13
  1175.                 ProcessAbruptExit(statement -> BreakStatementCast() -> nesting_level);
  1176.             EmitBranch(OP_GOTO,break_labels[statement -> BreakStatementCast() -> nesting_level]);
  1177.             abrupt = 1;
  1178.             break;
  1179.         case Ast::CONTINUE:                 // JLS 13.14
  1180.             ProcessAbruptExit(statement -> ContinueStatementCast() -> nesting_level);
  1181.             EmitBranch(OP_GOTO,continue_labels[statement -> ContinueStatementCast() -> nesting_level]);
  1182.             abrupt = 1;
  1183.             break;
  1184.         case Ast::RETURN:                   // JLS 13.15
  1185.             EmitReturnStatement(statement -> ReturnStatementCast());
  1186.             abrupt = 1;
  1187.             break;
  1188.         case Ast::SUPER_CALL: 
  1189.             EmitSuperInvocation((AstSuperCall *) statement);
  1190.             break;
  1191.         case Ast::THIS_CALL: 
  1192.             EmitThisInvocation((AstThisCall *) statement);
  1193.             break;
  1194.         case Ast::THROW:                        // JLS 13.16
  1195.             EmitExpression(statement -> ThrowStatementCast() -> expression);
  1196.             PutOp(OP_ATHROW);
  1197.             abrupt = 1;
  1198.             break;
  1199.         case Ast::SYNCHRONIZED_STATEMENT:   // JLS 13.17
  1200.             EmitSynchronizedStatement(statement -> SynchronizedStatementCast());
  1201.             break;
  1202.         case Ast::TRY:                      // JLS 13.18
  1203.             EmitTryStatement(statement -> TryStatementCast());
  1204.             break;
  1205.         case Ast::CLASS: // Class Declaration
  1206.         case Ast::INTERFACE: // InterfaceDeclaration
  1207.                 // these are factored out by the front end; and so must be skipped here
  1208.             break;
  1209.         case Ast::CATCH:                    // JLS 13.18
  1210.         case Ast::FINALLY:                  // JLS 13.18
  1211.                 // handled by TryStatement
  1212.         default:
  1213.             chaos("unknown statement kind");
  1214.             break;
  1215.     }
  1216.     return abrupt;
  1217. }
  1218. void ByteCode::EmitReturnStatement(AstReturnStatement * statement)
  1219. {
  1220.     int var_index=-1;
  1221.     int i;
  1222.     if (statement -> expression_opt == NULL) { // no return value
  1223.         ProcessAbruptExit(0);
  1224.         PutOp(OP_RETURN);
  1225.         return;
  1226.     }
  1227.     TypeSymbol * return_type = statement -> expression_opt-> Type();
  1228.  
  1229.     EmitExpression(statement -> expression_opt);
  1230.     if (method_type != return_type) {
  1231.       // no need to cast from reference to Object -- always ok
  1232.       if (method_type == this_control.Object() && IsReferenceType(return_type)) {
  1233.       }
  1234.       else {
  1235.           EmitCast(method_type, return_type);
  1236.       }
  1237.     }
  1238.     if (synchronized_blocks) {
  1239.     // if any outstanding synchronized blocks
  1240.     // find the index of the innermost enclosing block that is
  1241.     // synchronized. This block will have the variables allocated
  1242.     // for saving synchronization information.
  1243.         int synch_block=this_block_depth;
  1244.         for (i=this_block_depth;;i--) {
  1245.             if (is_synchronized[i]) {
  1246.             synch_block = i;
  1247.             break;
  1248.             }
  1249.             else if (i==0) {
  1250.               chaos("unable to find synchronization block");
  1251.             }
  1252.         }
  1253.  
  1254.         var_index=block_symbols[synch_block] -> synchronized_variable_index+2;;
  1255.  
  1256. //        if (this_control.IsDoubleWordType(return_type)) var_index--;
  1257.  
  1258.     }
  1259.     else if (finally_blocks) {
  1260.         for (i=this_block_depth;;i--) {
  1261.             if (has_finally_clause[i]) {
  1262.             var_index = has_finally_clause[i] - 1;
  1263.         var_index += 2; // move to start of area to save value 
  1264.             break;
  1265.             }
  1266.             else if (i==0) {
  1267.               chaos("unable to find finally block");
  1268.             }
  1269.         }
  1270.     }
  1271.     if (var_index >= 0) { // if need to save before abrupt exit 
  1272.         StoreLocal(var_index, method_type);
  1273.         ProcessAbruptExit(0);
  1274.         LoadLocal(var_index, method_type);
  1275.     }
  1276.     if (method_type != this_control.void_type) GenerateReturn(method_type);
  1277. }
  1278.  
  1279. int ByteCode::EmitBlockStatement(AstBlock *block, int synchronized)
  1280. {
  1281.     BlockSymbol *block_symbol = block -> block_symbol;
  1282.     int nesting_level = block -> nesting_level;
  1283.  
  1284.     int length=0;
  1285.     int start_pc;
  1286.     int save_depth = this_block_depth;
  1287.     int this_depth = nesting_level;
  1288. #ifdef TBSL 
  1289.     AstStatement * last_statement;
  1290. #endif  
  1291.     int i;
  1292.     int last_kind=0;
  1293.  
  1294.     this_block_depth =  nesting_level;
  1295.     is_synchronized[this_depth] = synchronized;
  1296.     synchronized_blocks += synchronized;
  1297.     block_symbols[this_depth] = block_symbol;
  1298.     start_pc = code_attribute -> code.Length();
  1299.     stack_depth = 0; // stack empty at start of statement
  1300.  
  1301.     if (this_depth>max_block_depth) {
  1302.         cout << "this_depth " << this_depth << "max " << max_block_depth << "\n";
  1303.         chaos("loops too deeply nested");
  1304.     }
  1305.  
  1306.     if (block -> NumStatements() > 0) {
  1307.     for (i=0; i<block -> NumStatements();i++){
  1308.         last_kind = EmitStatement((AstStatement *) block -> Statement(i));
  1309.     }
  1310.     if (this_block_depth != this_depth) {
  1311.       chaos("block depth out of synch!");
  1312.     }
  1313. //    this_block_depth = this_depth; // in case altered by one of above blocks
  1314.     }
  1315.  
  1316.     // if last statement is if_statement, must supply NOP to serve
  1317.     // as target for branch from true part
  1318.     // TODO - must refine this test so detect other cases where may
  1319.     // need following code, such as Switch, For, While; but
  1320.     // not if procedure returns void
  1321.     // code to end block (former end_block())
  1322.     // always define LABEL_BREAK at this point, and complete definition
  1323.     // of other labels
  1324.  
  1325.     if (IsLabelUsed(break_labels[this_depth])) {
  1326.         // need define only if used
  1327.         DefineLabel(break_labels[this_depth]);
  1328.     }
  1329.     CompleteLabel(begin_labels[this_depth]);
  1330.     CompleteLabel(break_labels[this_depth]);
  1331.     CompleteLabel(continue_labels[this_depth]);
  1332.     CompleteLabel(test_labels[this_depth]);
  1333.     CompleteLabel(begin_labels[this_depth]);
  1334.     if (is_synchronized[this_depth]) synchronized_blocks--;
  1335. //    if (this_block_depth) this_block_depth--;
  1336. #ifdef TBSL
  1337.         if (block_statements) {
  1338.     if (block -> NumStatements()) {
  1339.         last_statement = (AstStatement *) block -> Statement(block -> NumStatements()-1);
  1340.         if (last_statement -> IfStatementCast()) {
  1341.             PutNop(1);
  1342.         }
  1343.     }
  1344.     }
  1345. #endif  
  1346.     // compute local variable table and max variable number
  1347.     UpdateBlockInfo(block_symbol);
  1348.     this_block_depth = save_depth;
  1349.     return last_kind;
  1350. }
  1351. void ByteCode::EmitStatementExpression(AstExpression * expression)
  1352. {
  1353.     switch (expression -> kind) {
  1354.         case Ast::PARENTHESIZED_EXPRESSION:
  1355.                 {
  1356.             AstParenthesizedExpression * pe =
  1357.                                               (AstParenthesizedExpression *) expression;   
  1358.             EmitStatementExpression(pe -> expression);
  1359.                 }
  1360.                 break;
  1361.         case Ast::CALL:
  1362.             (void) EmitMethodInvocation((AstMethodInvocation *)expression, 0);
  1363.             if (expression-> Type()!=this_control.void_type) {
  1364.                 if (this_control.IsDoubleWordType(expression-> Type())) {
  1365.                     PutOp(OP_POP2);
  1366.                 }
  1367.                 else {
  1368.                     PutOp(OP_POP); // discard value if used as statement
  1369.                 }
  1370.             }
  1371.             break;
  1372.         case Ast::POST_UNARY:
  1373.             (void) EmitPostUnaryExpression((AstPostUnaryExpression *)expression,0);
  1374.             break;
  1375.         case Ast::PRE_UNARY:
  1376.             (void) EmitPreUnaryExpression((AstPreUnaryExpression *)expression,0);
  1377.             break;
  1378.         case Ast::ASSIGNMENT:
  1379.             EmitAssignmentExpression((AstAssignmentExpression *)expression,0);
  1380.             break;
  1381.     case Ast::CLASS_CREATION:
  1382.         (void) EmitClassInstanceCreationExpression((AstClassInstanceCreationExpression *) expression, 0);
  1383.             break;
  1384.         default:
  1385.         chaos("invalid statement expression kind");
  1386.     }
  1387. }
  1388. void ByteCode::EmitSwitchStatement(AstSwitchStatement * sws)
  1389. {
  1390.     // generate code for switch statement. Good code generation requires
  1391.     // detailed knowledge of the target machine. Lacking this, we simply
  1392.     // choose between LOOKUPSWITCH and TABLESWITCH by picking that
  1393.     // opcode that takes the least number of bytes in the byte code.
  1394.     int use_lookup=0; // set if using LOOKUPSWITCH opcode
  1395.     // compare sizes os generated opcodes, ignoring size of common
  1396.     // header (opcode through default bytes).
  1397.     int high,low,ncases,switch_depth;
  1398.     int has_default;
  1399.     int op_start;
  1400.     int i;
  1401.     int nlabels;
  1402.     int map_index;
  1403.     int label_index;
  1404.     int start_pc;
  1405.     int ci;
  1406.     int di;
  1407.     AstBlock *switch_block=sws -> switch_block;
  1408.     BlockSymbol * block_symbol = switch_block -> block_symbol;
  1409.     switch_depth = sws -> switch_block -> nesting_level;
  1410.     EmitBlockStatement(switch_block, 0);
  1411.     // We need only worry about the presence of a default case if there
  1412.     // is code for it.
  1413.     start_pc = code_attribute -> code.Length();
  1414.     has_default = sws -> default_case.switch_block_statement!=NULL ? 1 : 0;
  1415.     ncases = sws -> map.Length();
  1416.     // Use tableswitch if have exact match or size of tableswitch
  1417.     // case is no more than 30 bytes more code than lookup case
  1418.     use_lookup=1;
  1419.     nlabels=ncases;
  1420.  
  1421.     if (ncases) {
  1422.       low = sws -> map[0] -> Value();
  1423.       high = sws -> map[ncases-1] -> Value();
  1424.       // want to compute
  1425.       //  (2+high-low+1)<(1+ncases*2+30
  1426.       // but must guard against overflow, so factor out
  1427.       //  high - low < ncases*2 + 28
  1428.       // but can't have number of labels < number of cases
  1429.       if ((high-low) < (ncases*2+28)) {
  1430.         use_lookup = 0;     // use tableswitch
  1431.         nlabels = high-low + 1;
  1432.       }
  1433.       // correct estimate in case above computation gave ridiculous number
  1434.       // for the number of labels. (This is problem 096)
  1435.       if (nlabels < ncases) {
  1436.     use_lookup = 1;
  1437.     nlabels = ncases;
  1438.       }
  1439.     }
  1440.  
  1441.     EmitExpression(sws -> expression);
  1442.     stack_depth=0;
  1443.     PutOp(use_lookup ? OP_LOOKUPSWITCH : OP_TABLESWITCH);
  1444.     op_start = last_op_pc;  // pc at start of instruction
  1445.     // supply any needed padding
  1446.     while(code_attribute -> code.Length() % 4) {
  1447.         PutNop(0);
  1448.     }  
  1449.     // note that if no default clause in switch statement, must allocate
  1450.     // one that corresponds to do nothing and branches to start of next
  1451.     // statement.
  1452.     Label default_label;
  1453.     UseLabel(has_default ? default_label :
  1454.               break_labels[switch_depth],
  1455.               4,code_attribute -> code.Length()-op_start);
  1456.  
  1457.     if (use_lookup) PutU4(ncases);
  1458.     else {
  1459.         PutU4(low);
  1460.         PutU4(high);
  1461.     }
  1462.     // how to allocate for proper length
  1463.     Label *case_labels = new Label[(use_lookup ? ncases : nlabels) + 1];
  1464.  
  1465.     if (use_lookup == 0) {
  1466.         int *has_tag = new int[nlabels + 1];
  1467.         for (i = 0; i < nlabels; i++) has_tag[i] = 0;
  1468.         // mark cases for which no case tag available, i.e., default cases
  1469.  
  1470.         for (i=0;i<sws -> switch_block -> NumStatements();i++) {
  1471.             int li;
  1472.  
  1473.             AstSwitchBlockStatement * sbs = (AstSwitchBlockStatement *)
  1474.                                              sws -> switch_block -> Statement(i);
  1475.             // process labels for this block
  1476.             for (li=0;li<sbs -> NumSwitchLabels();li++) {
  1477.                 if (sbs -> SwitchLabel(li) -> CaseLabelCast()) {
  1478.                     map_index =sbs -> SwitchLabel(li) -> CaseLabelCast() -> map_index;
  1479.                     di =sws -> map[map_index] -> index;
  1480.                     //                  label_index = sws -> map[di] -> Value() - low;
  1481.                     label_index = sws -> map[map_index] -> Value() - low;
  1482.                     has_tag[label_index]=1;
  1483.  
  1484.                 }
  1485.             }
  1486.         }
  1487.         // now emit labels in instruction, using appropriate index
  1488.         for (i=0;i<nlabels;i++) {
  1489.             UseLabel(has_tag[i]  ? case_labels[i] :
  1490.                       has_default ? default_label 
  1491.                                   : break_labels[switch_depth],
  1492.                       4,code_attribute -> code.Length()-op_start);
  1493.         }
  1494.  
  1495.         delete [] has_tag;
  1496.     }
  1497.     else {
  1498.         for (i=0;i<ncases;i++) {
  1499.             PutU4(sws -> map[i] -> Value());
  1500.             UseLabel(case_labels[sws -> map[i] -> index],4,code_attribute -> code.Length()-op_start);
  1501.         }
  1502.     }
  1503.     // march through switch block statements, compiling blocks in
  1504.     // proper order. We must respect order in which blocks seen
  1505.     // so that blocks lacking a terminal break fall through to the
  1506.     // proper place.
  1507.     for (i=0;i<sws -> switch_block -> NumStatements();i++) {
  1508.         int li;
  1509.  
  1510.         AstSwitchBlockStatement * sbs = (AstSwitchBlockStatement *)
  1511.                                          sws -> switch_block -> Statement(i);
  1512.         // process labels for this block
  1513.         for (li=0;li<sbs -> NumSwitchLabels();li++) {
  1514.             if (sbs -> SwitchLabel(li) -> CaseLabelCast()) {
  1515.                 map_index =sbs -> SwitchLabel(li) -> CaseLabelCast() -> map_index;
  1516.                 if (use_lookup) {
  1517.                     DefineLabel(case_labels[map_index]);
  1518.                 }
  1519.                 else {
  1520.                     int found=0;
  1521.                     // look for case with same index and
  1522.                     // use its value to find label index.
  1523.                     for (int di2=0;di2<sws -> map.Length();di2++) {
  1524.                         if (sws -> map[di2] -> index==map_index) {
  1525.                             ci = sws -> map[di2] -> Value()-low;
  1526.                             DefineLabel(case_labels[ci]);
  1527.                             found=1;
  1528.                             break;
  1529.                         }
  1530.                     }
  1531.                     if (found==0) 
  1532.                         chaos("unable to find case label");
  1533.                 }
  1534.             }
  1535.             else {
  1536.                 if (sbs -> SwitchLabel(li) -> DefaultLabelCast()) {
  1537.                     if (has_default) {
  1538.                         DefineLabel(default_label);
  1539.                     }
  1540.                     else {
  1541.                         chaos("error in processing default label");
  1542.                     }
  1543.                 }
  1544.             }
  1545.         }
  1546.         // compile code for this case
  1547.         for (li=0;li<sbs -> NumStatements();li++) {
  1548.             (void) EmitStatement(sbs -> Statement(li) -> StatementCast());
  1549.         }
  1550.     }
  1551.     UpdateBlockInfo(block_symbol);
  1552.     for (i=0;i<nlabels;i++) {
  1553.         if (case_labels[i].uses.Length() && case_labels[i].defined==0) {
  1554.             case_labels[i].defined=1;
  1555.         if (has_default) {
  1556.             case_labels[i].definition=default_label.definition;
  1557.         }
  1558.         else {
  1559.             case_labels[i].definition = break_labels[switch_depth].definition;
  1560.         }
  1561.         }
  1562.         CompleteLabel(case_labels[i]);
  1563.     }
  1564.  
  1565.     if (has_default) {
  1566.         CompleteLabel(default_label);
  1567.     }
  1568.     // define target of break label
  1569.     if (IsLabelUsed(break_labels[switch_depth])) {                   // need define only if used
  1570.         DefineLabel(break_labels[switch_depth]);
  1571.     }
  1572.     for (i=0;i<nlabels;i++) {
  1573.         if (case_labels[i].uses.Length() && case_labels[i].defined==0) {
  1574.             case_labels[i].defined=1;
  1575.         if (has_default) {
  1576.             case_labels[i].definition=default_label.definition;
  1577.         }
  1578.         else {
  1579.             case_labels[i].definition = break_labels[switch_depth].definition;
  1580.         }
  1581.         }
  1582.         CompleteLabel(case_labels[i]);
  1583.     }
  1584.  
  1585.     if (has_default) {
  1586.         CompleteLabel(default_label);
  1587.     }
  1588.     // define target of break label
  1589.     if (IsLabelUsed(break_labels[switch_depth])) {               // need define only if used
  1590.         CompleteLabel(break_labels[switch_depth]);
  1591.     }
  1592.  
  1593.  
  1594.     // note that if using table, then must provide slot for every
  1595.     // entry in the range low..high, even though the user may not
  1596.     // have provided an explicit entry, in which case the default
  1597.     // action is to be taken. For example
  1598.     // switch (e) {
  1599.     //  case 1:2:3: act1; break;
  1600.     //  case 5:6:   act2; break;
  1601.     //  default: defact; break;
  1602.     // }
  1603.     // translated as
  1604.     // switch (e)
  1605.     // switch (e) {
  1606.     //  case 1:2:3: act1; break;
  1607.     //  case 4: goto defa:
  1608.     //  case 5:6:   act2; break;
  1609.     //  defa:
  1610.     //  default: defact; 
  1611.     // }
  1612.  
  1613.     delete [] case_labels;
  1614. }
  1615.  
  1616.  
  1617.  
  1618. //  13.18       The try statement
  1619. void ByteCode::EmitTryStatement(AstTryStatement * statement)
  1620. {
  1621.     AstFinallyClause * finally_clause;
  1622.     int start_pc,end_pc;
  1623.     int exception_index,handler_pc;
  1624.     Label end_label;
  1625.     AstCatchClause * catch_clause;
  1626.     int last_abrupt=0; // set if last statement in try block is abrupt exit
  1627.     int try_depth = statement -> block -> nesting_level - 1;;
  1628.     int final_depth = try_depth + 1;
  1629.     BlockSymbol * block_symbol;
  1630.     start_pc = code_attribute -> code.Length(); // start pc
  1631.     if (statement -> finally_clause_opt) { 
  1632.     // call finally block if have finally handler
  1633. assert(block_symbols[try_depth]);
  1634.         block_symbol = block_symbols[try_depth] -> BlockCast();
  1635.         finally_clause = statement -> finally_clause_opt;
  1636.         has_finally_clause[final_depth]=1 + block_symbol -> try_variable_index;
  1637.         finally_blocks++;
  1638.     }
  1639.     last_abrupt = EmitStatement(statement -> block);
  1640.     // increment max_stack in case exception thrown while stack at greatest depth
  1641.     code_attribute -> max_stack++;
  1642.     if (statement -> finally_clause_opt) { // call finally block if have finally handler
  1643.         PutOp(OP_JSR);
  1644.         UseLabel(final_labels[final_depth], 2, 1);
  1645.     }
  1646.     
  1647.     if (!last_abrupt) {
  1648.         EmitBranch(OP_GOTO,end_label);
  1649.     }
  1650.     PutNop(0); // emit NOP so end_pc will come out right
  1651.     end_pc = last_op_pc;
  1652. // process catch clauses
  1653.     int catch_abrupt=0;
  1654.     for (int i = 0; i<statement -> NumCatchClauses();i++) {
  1655.         catch_clause = statement -> CatchClause(i);
  1656.         VariableSymbol * parameter_symbol = catch_clause -> parameter_symbol;
  1657.         handler_pc = code_attribute -> code.Length();
  1658.         StoreLocalVariable(parameter_symbol);
  1659.         catch_abrupt = EmitStatement(catch_clause -> block);
  1660.         
  1661.         exception_index = code_attribute -> exception_table.NextIndex();
  1662.         code_attribute -> exception_table[exception_index].start_pc = start_pc;
  1663.         // add 1 to end_pc since it is exclusive, while start_pc
  1664.         // is inclusive. See footnote in 4.4.4 of JVM Specification
  1665.         //code_attribute -> exception_table[exception_index].end_pc = end_pc + 1; // DS 11 feb
  1666.         code_attribute -> exception_table[exception_index].end_pc = end_pc; // DS 11 feb
  1667.         code_attribute -> exception_table[exception_index].handler_pc = handler_pc;
  1668.         code_attribute -> exception_table[exception_index].catch_type =
  1669.             RegisterClass(parameter_symbol-> Type() -> fully_qualified_name);
  1670.         if (statement -> finally_clause_opt) { // call finally block if have finally handler
  1671.             PutOp(OP_JSR);
  1672.             UseLabel(final_labels[final_depth], 2, 1);
  1673.         }
  1674.         if (! catch_abrupt) {
  1675.                 EmitBranch(OP_GOTO,end_label);
  1676.         }
  1677.     }
  1678.  
  1679.     
  1680.     if (statement -> finally_clause_opt) {
  1681.         handler_pc = code_attribute -> code.Length();
  1682.         has_finally_clause[final_depth] = 0; // reset once finally clause processed
  1683.         finally_blocks--;
  1684.  
  1685.         // handler for finally()
  1686.  
  1687.         // push thrown value
  1688.         StoreLocal(block_symbol -> try_variable_index, this_control.Object());
  1689.         PutOp(OP_JSR);
  1690.         UseLabel(final_labels[final_depth], 2, 1);
  1691.         LoadLocal(block_symbol -> try_variable_index, this_control.Object());
  1692.         PutOp(OP_ATHROW);  // and rethrow the value to the invoker
  1693.  
  1694.         DefineLabel(final_labels[final_depth]);
  1695.         CompleteLabel(final_labels[final_depth]);
  1696.         StoreLocal(block_symbol -> try_variable_index+1, this_control.Object()); // save return address
  1697.         (void) EmitStatement(statement -> finally_clause_opt -> block);
  1698.         PutOp(OP_RET);
  1699.         PutU1(block_symbol -> try_variable_index + 1); // return using saved address
  1700.         exception_index = code_attribute -> exception_table.NextIndex();
  1701.         code_attribute -> exception_table[exception_index].start_pc = start_pc;
  1702.         code_attribute -> exception_table[exception_index].end_pc = handler_pc;
  1703.         code_attribute -> exception_table[exception_index].handler_pc = handler_pc;
  1704.         code_attribute -> exception_table[exception_index].catch_type = 0;
  1705.     }
  1706.  
  1707.     if (IsLabelUsed(end_label)) {
  1708.         DefineLabel(end_label);
  1709.         CompleteLabel(end_label);
  1710.         PutNop(1); // to make sure have code after end of try statement
  1711.     }
  1712.     else {
  1713.         CompleteLabel(end_label);
  1714.     }
  1715. }
  1716.  
  1717. void ByteCode::UpdateBlockInfo(BlockSymbol * block_symbol)
  1718. {
  1719.     int i;
  1720.  
  1721.     if (code_attribute -> max_locals<block_symbol -> max_variable_index) {
  1722.         code_attribute -> max_locals = block_symbol -> max_variable_index;
  1723.     }
  1724.     if (block_symbol == (BlockSymbol *) 0) {
  1725.       chaos("null block symbol");
  1726.     }
  1727.       
  1728.  
  1729.     if (this_control.option.g) {
  1730.     // compute local variable table
  1731.         for (i = 0; i < block_symbol -> NumVariableSymbols();i++) {
  1732.             VariableSymbol * sym = block_symbol -> VariableSym(i);
  1733.         // only make entry if defined within range
  1734.         if (last_op_pc > sym -> local_program_counter) {
  1735.                 AddLocalVariableTableEntry(sym -> local_program_counter, 
  1736.             last_op_pc - sym -> local_program_counter,
  1737.                     RegisterUtf8(sym -> ExternalIdentity() -> Utf8_literal),
  1738.                     RegisterUtf8(sym-> Type() -> signature),
  1739.                     sym -> LocalVariableIndex());
  1740.         }
  1741.         }
  1742.     }
  1743. }
  1744.  
  1745. void ByteCode::ProcessAbruptExit(int to_lev)
  1746. {
  1747.     // exit to block at level lev, freeing monitor locks and invoking finally clauses as appropriate
  1748.     for (int lev=this_block_depth;lev>to_lev;lev--) {
  1749.         if (has_finally_clause[lev]) {
  1750.             PutOp(OP_JSR);
  1751.             UseLabel(final_labels[lev], 2, 1);
  1752.         }
  1753.         else if (is_synchronized[lev]) {
  1754.             PutOp(OP_JSR);
  1755.             UseLabel(monitor_labels[lev], 2, 1);
  1756.         }
  1757.     }
  1758.  
  1759. }
  1760.  
  1761. void ByteCode::EmitBranch(unsigned int opc, Label& lab) {
  1762.     // generate branch
  1763.     PutOp(opc);
  1764.     UseLabel(lab,2,1);
  1765. }
  1766.  
  1767.  
  1768. void ByteCode::EmitBranchIfExpression(AstExpression *p, bool cond,Label &lab)
  1769. {
  1770.     // java provides a variety of conditional branch instructions, so
  1771.     // that a number of operators merit special handling:
  1772.     //      constant operand
  1773.     //      negation (we eliminate it)
  1774.     //      equality
  1775.     //      && and || (partial evaluation)
  1776.     //      comparisons
  1777.     // Other expressions are just evaluated and the appropriate
  1778.     // branch emitted.
  1779.     AstExpression *left,*right,*temp;
  1780.     AstPreUnaryExpression *pre;
  1781.     TypeSymbol *left_type, *right_type;
  1782.  
  1783.     if (p -> ParenthesizedExpressionCast()) {
  1784.         p = UnParenthesize(p);
  1785.     }
  1786.     if (p -> IsConstant()) {
  1787.         if (IsZero(p)) {
  1788.             if (cond == false)  EmitBranch(OP_GOTO,lab);
  1789.         }
  1790.         else {
  1791.             if (cond == true)  EmitBranch(OP_GOTO,lab);
  1792.         }
  1793.         return;
  1794.     }
  1795.     pre = p -> PreUnaryExpressionCast();
  1796.     if (pre) { // must be !, though should probably
  1797.  
  1798.         // branch_if(!e,c,l) => branch_if(e,!c,l)
  1799.         // test opcode
  1800.         // call again with complementary control expression to show
  1801.         // effect of negation
  1802.         if (pre -> pre_unary_tag == AstPreUnaryExpression::NOT) {
  1803.             EmitBranchIfExpression(pre -> expression,cond == true ? false : true, lab);
  1804.             return;
  1805.         }
  1806.         else {
  1807.             chaos("branch_if expects ! in this context");
  1808.         }
  1809.     }
  1810.     // dispose of non-binary expression case by just evaluating
  1811.     // operand and emitting appropiate test.
  1812.     if (!(p -> BinaryExpressionCast())) {
  1813.         EmitExpression(p);
  1814.         EmitBranch(cond == true ? OP_IFNE : OP_IFEQ,lab);
  1815.         return;
  1816.     }
  1817.     // Here if binary expression, so extract operands
  1818.     AstBinaryExpression * bp = (AstBinaryExpression *) p;
  1819.     left = bp -> left_expression;
  1820.     if (left -> ParenthesizedExpressionCast()) {
  1821.         left = UnParenthesize(left);
  1822.     }
  1823.     right = bp -> right_expression;
  1824.     if (right -> ParenthesizedExpressionCast()) {
  1825.         right = UnParenthesize(right);
  1826.     }
  1827.     left_type = left-> Type();
  1828.     right_type = right-> Type();
  1829.     switch (bp -> binary_tag) {
  1830.         case AstBinaryExpression::INSTANCEOF:
  1831.                 {
  1832.             EmitExpression(left);
  1833.             PutOp(OP_INSTANCEOF);
  1834.         TypeSymbol * instanceof_type = bp -> right_expression-> Type();
  1835.         if (instanceof_type -> num_dimensions) {
  1836.             PutU2(RegisterClass(instanceof_type -> signature));
  1837.         }
  1838.         else {
  1839.             PutU2(RegisterClass(instanceof_type -> fully_qualified_name));
  1840.         }
  1841.             EmitBranch(cond == true? OP_IFNE : OP_IFEQ,lab);
  1842.                 }
  1843.                 return;
  1844.         case AstBinaryExpression::AND_AND:
  1845.                 /*
  1846.                 branch_if(a&&b, true, lab) =>
  1847.                 branch_if(a,false,skip);
  1848.                 branch_if(b,true,lab);
  1849.                 skip:
  1850.                 branch_if(a&&b, false, lab) =>
  1851.                 branch_if(a,false,lab);
  1852.                 branch_if(b,false,lab);
  1853. */
  1854.                 if (cond == true) {
  1855.             Label skip;
  1856.             EmitBranchIfExpression(left, false, skip);
  1857.             EmitBranchIfExpression(right, true, lab);
  1858.             DefineLabel(skip);
  1859.             CompleteLabel(skip);
  1860.         }
  1861.                 else {
  1862.                     EmitBranchIfExpression(left, false, lab);
  1863.                     EmitBranchIfExpression(right, false, lab);
  1864.                 }
  1865.                 return;
  1866.         case AstBinaryExpression::OR_OR:
  1867.                 /*
  1868.                 branch_if(a||b,true,lab) =>
  1869.                 branch_if(a,true,lab);
  1870.                 branch_if(b,true,lab);
  1871.                 branch_if(a||b,false,lab) =>
  1872.                 branch_if(a,true,skip);
  1873.                 branch_if(b,false,lab);
  1874.                 There is additional possibility of one of the operands being
  1875.                 constant that should be dealt with at some point.
  1876. */
  1877.                 if (cond == true) {
  1878.             EmitBranchIfExpression(left, true, lab);
  1879.             EmitBranchIfExpression(right, true, lab);
  1880.         }
  1881.                 else {
  1882.                     Label skip;  
  1883.                     EmitBranchIfExpression(left, true, skip);
  1884.                     EmitBranchIfExpression(right, false, lab);
  1885.                     DefineLabel(skip);
  1886.                     CompleteLabel(skip);
  1887.                 }
  1888.                 return;
  1889.         case AstBinaryExpression::EQUAL_EQUAL:
  1890.         case AstBinaryExpression::NOT_EQUAL:
  1891.                 // see if test against null
  1892.                 if (left_type == this_control.null_type || right_type==this_control.null_type) {
  1893.             // arrange so right operand is null
  1894.             if (left_type == this_control.null_type) {
  1895.                 temp = left;left = right;right = temp;
  1896.                 left_type = left-> Type(); right_type = right-> Type();
  1897.             }
  1898.             EmitExpression(left);
  1899.             if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
  1900.                 EmitBranch(cond == true? OP_IFNULL : OP_IFNONNULL,lab);
  1901.             }
  1902.             else {
  1903.                 EmitBranch(cond == true ? OP_IFNONNULL : OP_IFNULL,lab);
  1904.             }
  1905.             return;
  1906.         }
  1907.                 // see if test against integer zero
  1908.                 if (IsZero(left) || IsZero(right)) {
  1909.                     // arrange so right operand is zero
  1910.                     if (IsZero(left)) { 
  1911.                         temp = left;left = right;right = temp;
  1912.                         left_type = left-> Type();right_type = right-> Type();
  1913.                     } 
  1914.                     EmitExpression(left);
  1915.                     if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
  1916.                         EmitBranch(cond == true? OP_IFEQ : OP_IFNE,lab);
  1917.                         return;
  1918.                     }
  1919.                     else {
  1920.                         EmitBranch(cond == true ? OP_IFNE : OP_IFEQ,lab);
  1921.                     }
  1922.                     return;
  1923.                 }
  1924.                 // see if test of integers
  1925.                 if ((this_control.IsSimpleIntegerValueType(left_type)||left_type==this_control.boolean_type) && 
  1926.                     (this_control.IsSimpleIntegerValueType(right_type)
  1927.                      || right_type == this_control.boolean_type) ) {
  1928.                     EmitExpression(left);
  1929.                     EmitExpression(right);
  1930.                     if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
  1931.                         EmitBranch(cond ? OP_IF_ICMPEQ : OP_IF_ICMPNE,lab);
  1932.                         return;
  1933.                     }
  1934.                     else {
  1935.                         EmitBranch(cond ? OP_IF_ICMPNE : OP_IF_ICMPEQ,lab);
  1936.                     }
  1937.                     return;
  1938.                 }
  1939.                 else if (IsReferenceType(left_type) && IsReferenceType(right_type)) {
  1940.                     // else just do the comparison
  1941.                     EmitExpression(left);
  1942.                     EmitExpression(right);
  1943.                     if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
  1944.                         EmitBranch(cond ? OP_IF_ACMPEQ : OP_IF_ACMPNE,lab);
  1945.                     }
  1946.                     else {
  1947.                         EmitBranch(cond ? OP_IF_ACMPNE : OP_IF_ACMPEQ,lab);
  1948.                     }
  1949.                     return;
  1950.                 }
  1951.     }
  1952.  
  1953.     // here if not comparison, comparison for non-integral numeric types, or
  1954.     // integral comparison for which no special casing needed.
  1955.     // Begin by dealing with non-comparisons
  1956.     switch(bp -> binary_tag) {
  1957.         case AstBinaryExpression::LESS:
  1958.         case AstBinaryExpression::LESS_EQUAL:
  1959.         case AstBinaryExpression::GREATER:
  1960.         case AstBinaryExpression::GREATER_EQUAL:
  1961.         case AstBinaryExpression::EQUAL_EQUAL:
  1962.         case AstBinaryExpression::NOT_EQUAL:
  1963.                 break; // break to continue comparison processing
  1964.         default:
  1965.             // not a comparison, get the (necessarily boolean) value
  1966.             // of the expression and branch on the result
  1967.             EmitExpression(p);
  1968.             EmitBranch(cond ? OP_IFNE : OP_IFEQ, lab);
  1969.             return;
  1970.     }
  1971.     unsigned opcode = 0;
  1972.     unsigned int op_true, op_false;
  1973.     if (this_control.IsSimpleIntegerValueType(left_type)
  1974.         || left_type == this_control.boolean_type) {
  1975.         // we have already dealt with EQUAL_EQUAL and NOT_EQUAL for
  1976.         // integers, but still need to look for comparisons for which
  1977.         // one operand may be zero.
  1978.         if (IsZero(left)) {
  1979.             EmitExpression(right);
  1980.             switch(bp -> binary_tag) {
  1981.                 case AstBinaryExpression::LESS: // if (0<x) same as  if (x>0)
  1982.                     op_true = OP_IFGT; op_false = OP_IFLE; break;
  1983.                 case AstBinaryExpression::LESS_EQUAL:  // if (0<=x) same as if (x>=0)
  1984.                     op_true = OP_IFGE; op_false = OP_IFLT; break;
  1985.                 case AstBinaryExpression::GREATER:  // if (0>x) same as if (x<0)
  1986.                     op_true = OP_IFLT; op_false = OP_IFGE; break;
  1987.                 case AstBinaryExpression::GREATER_EQUAL: // if (0>=x) same as if (x<=0)
  1988.                     op_true = OP_IFLE; op_false = OP_IFGT; break;
  1989.             }
  1990.         }
  1991.         else if (IsZero(right)) {
  1992.             EmitExpression(left);
  1993.             switch(bp -> binary_tag) {
  1994.                 case AstBinaryExpression::LESS:
  1995.                     op_true = OP_IFLT; op_false = OP_IFGE; break;
  1996.                 case AstBinaryExpression::LESS_EQUAL:
  1997.                     op_true = OP_IFLE; op_false = OP_IFGT; break;
  1998.                 case AstBinaryExpression::GREATER:
  1999.                     op_true = OP_IFGT; op_false = OP_IFLE; break;
  2000.                 case AstBinaryExpression::GREATER_EQUAL:
  2001.                     op_true = OP_IFGE; op_false = OP_IFLT; break;
  2002.             }
  2003.         }
  2004.         else {
  2005.             EmitExpression(left);
  2006.             EmitExpression(right);
  2007.             switch(bp -> binary_tag) {
  2008.                 case AstBinaryExpression::LESS:
  2009.                     op_true = OP_IF_ICMPLT; op_false = OP_IF_ICMPGE; break;
  2010.                 case AstBinaryExpression::LESS_EQUAL:
  2011.                     op_true = OP_IF_ICMPLE; op_false = OP_IF_ICMPGT; break;
  2012.                 case AstBinaryExpression::GREATER:
  2013.                     op_true = OP_IF_ICMPGT; op_false = OP_IF_ICMPLE; break;
  2014.                 case AstBinaryExpression::GREATER_EQUAL:
  2015.                     op_true = OP_IF_ICMPGE; op_false = OP_IF_ICMPLT; break;
  2016.             }
  2017.         }
  2018.     }
  2019.     else if (left_type == this_control.long_type) {
  2020.         EmitExpression(left);
  2021.         EmitExpression(right);
  2022.         opcode = OP_LCMP;
  2023.         // branch according to result value on stack
  2024.         switch (bp -> binary_tag) {
  2025.             case AstBinaryExpression::EQUAL_EQUAL:
  2026.                 op_true = OP_IFEQ; op_false = OP_IFNE; break;
  2027.             case AstBinaryExpression::NOT_EQUAL:
  2028.                 op_true = OP_IFNE; op_false = OP_IFEQ; break;
  2029.             case AstBinaryExpression::LESS:
  2030.                 op_true = OP_IFLT; op_false = OP_IFGE; break;
  2031.             case AstBinaryExpression::LESS_EQUAL:
  2032.                 op_true = OP_IFLE; op_false = OP_IFGT; break;
  2033.             case AstBinaryExpression::GREATER:
  2034.                 op_true = OP_IFGT; op_false = OP_IFLE; break;
  2035.             case AstBinaryExpression::GREATER_EQUAL:
  2036.                 op_true = OP_IFGE; op_false = OP_IFLT; break;
  2037.         }
  2038.     }
  2039.     else if (left_type == this_control.float_type) {
  2040.         EmitExpression(left);
  2041.         EmitExpression(right);
  2042.         switch (bp -> binary_tag) {
  2043.             case AstBinaryExpression::EQUAL_EQUAL:
  2044.                 opcode = OP_FCMPL; op_true = OP_IFEQ; op_false = OP_IFNE; break;
  2045.             case AstBinaryExpression::NOT_EQUAL:
  2046.                 opcode = OP_FCMPL; op_true = OP_IFNE; op_false = OP_IFEQ; break;
  2047.             case AstBinaryExpression::LESS:
  2048.                 opcode = OP_FCMPG; op_true = OP_IFLT; op_false = OP_IFGE; break;
  2049.             case AstBinaryExpression::LESS_EQUAL:
  2050.                 opcode = OP_FCMPG; op_true = OP_IFLE; op_false = OP_IFGT; break;
  2051.             case AstBinaryExpression::GREATER:
  2052.                 opcode = OP_FCMPL; op_true = OP_IFGT; op_false = OP_IFLE; break;
  2053.             case AstBinaryExpression::GREATER_EQUAL:
  2054.                 opcode = OP_FCMPL; op_true = OP_IFGE; op_false = OP_IFLT; break;
  2055.         }
  2056.     }
  2057.     else if (left_type == this_control.double_type) {
  2058.         EmitExpression(left);
  2059.         EmitExpression(right);
  2060.         switch (bp -> binary_tag) {
  2061.             case AstBinaryExpression::EQUAL_EQUAL:
  2062.                 opcode = OP_DCMPL; op_true = OP_IFEQ; op_false = OP_IFNE; break;
  2063.             case AstBinaryExpression::NOT_EQUAL:
  2064.                 opcode = OP_DCMPL; op_true = OP_IFNE; op_false = OP_IFEQ; break;
  2065.             case AstBinaryExpression::LESS:
  2066.                 opcode = OP_DCMPG; op_true = OP_IFLT; op_false = OP_IFGE; break;
  2067.             case AstBinaryExpression::LESS_EQUAL:
  2068.                 opcode = OP_DCMPG; op_true = OP_IFLE; op_false = OP_IFGT; break;
  2069.             case AstBinaryExpression::GREATER:
  2070.                 opcode = OP_DCMPL; op_true = OP_IFGT; op_false = OP_IFLE; break;
  2071.             case AstBinaryExpression::GREATER_EQUAL:
  2072.                 opcode = OP_DCMPL; op_true = OP_IFGE; op_false = OP_IFLT; break;
  2073.         }
  2074.     }
  2075.     else {
  2076.         chaos("comparison of unsupported type");
  2077.     }
  2078.     if (opcode) PutOp(opcode); // if need to emit comparison before branch
  2079.     EmitBranch (cond ? op_true: op_false, lab);
  2080. }
  2081.  
  2082. void ByteCode::EmitSynchronizedStatement(AstSynchronizedStatement * statement)
  2083. {
  2084.     int var_index; // local variable index to save address of object
  2085.     int loc_index; // local variable index to save address
  2086.     int start_pc,end_pc;
  2087.     int exception_index,handler_pc;
  2088.     Label end_label;
  2089.     var_index = statement -> block -> block_symbol -> synchronized_variable_index;
  2090.     loc_index = var_index+1;
  2091.     EmitExpression(statement -> expression);
  2092.     StoreLocal(var_index, this_control.Object()); // save address of object
  2093.     LoadLocal(var_index, this_control.Object()); // load address of object onto stack
  2094.  
  2095.     PutOp(OP_MONITORENTER); // enter monitor associated with object
  2096.     start_pc = code_attribute -> code.Length(); // start pc
  2097.     (void) EmitBlockStatement(statement -> block, 1);
  2098.     LoadLocal(var_index, this_control.Object()); // load address of object onto stack
  2099.     PutOp(OP_MONITOREXIT);
  2100.     if (statement -> block -> NumStatements() > 0) {
  2101.     end_pc = last_op_pc;
  2102.     EmitBranch(OP_GOTO,end_label); // branch around exception handler
  2103.     // reach here if any
  2104.     // increment max_stack in case exception thrown while stack at greatest depth
  2105.     code_attribute -> max_stack++;
  2106.     handler_pc = code_attribute -> code.Length();
  2107.     LoadLocal(var_index, this_control.Object()); // load address of object onto stack
  2108.     PutOp(OP_MONITOREXIT); 
  2109.     PutOp(OP_ATHROW);
  2110.     exception_index = code_attribute -> exception_table.NextIndex();
  2111.     code_attribute -> exception_table[exception_index].start_pc = start_pc;
  2112.     code_attribute -> exception_table[exception_index].end_pc = handler_pc;
  2113.     code_attribute -> exception_table[exception_index].handler_pc = handler_pc;
  2114.     code_attribute -> exception_table[exception_index].catch_type = 0;
  2115.     DefineLabel(monitor_labels[statement -> block -> nesting_level]);
  2116.     CompleteLabel(monitor_labels[statement -> block -> nesting_level]);
  2117.     StoreLocal(loc_index, this_control.Object()); // save return address
  2118.     LoadLocal(var_index, this_control.Object()); // load address of object onto stack
  2119.     PutOp(OP_MONITOREXIT); 
  2120.     PutOp(OP_RET);
  2121.     PutU1(loc_index);  // return using saved address
  2122.     DefineLabel(end_label);
  2123.     CompleteLabel(end_label);
  2124. //    EmitNop(1); // guarantee some PutOp after block in case
  2125.     // the synchronized statement is the last in the procedure.
  2126.     }
  2127. }
  2128.  
  2129. // JLS is Java Language Specification
  2130. // JVM is Java Virtual Machine
  2131. //
  2132. // Expressions: Chapter 14 of JLS
  2133.  
  2134. int ByteCode::EmitExpression(AstExpression *expression) 
  2135. {
  2136.     if (expression -> IsConstant()) {
  2137.         return LoadConstant(expression);
  2138.     }
  2139.     switch (expression -> kind) {
  2140.         case Ast::IDENTIFIER:
  2141.             if (expression -> SimpleNameCast() && expression -> SimpleNameCast() -> resolution_opt) {
  2142.                 return EmitExpression(expression -> SimpleNameCast() -> resolution_opt);
  2143.             }
  2144.             return LoadSimple(GetLHSKind(expression, (MethodSymbol *)0),expression);
  2145.         case Ast::INTEGER_LITERAL:
  2146.         case Ast::LONG_LITERAL:
  2147.         case Ast::FLOATING_POINT_LITERAL:
  2148.         case Ast::DOUBLE_LITERAL:
  2149.         case Ast::TRUE_LITERAL:
  2150.         case Ast::FALSE_LITERAL:
  2151.         case Ast::STRING_LITERAL:
  2152.         case Ast::CHARACTER_LITERAL:
  2153.         return LoadConstant(expression);
  2154.         case Ast::THIS_EXPRESSION:
  2155.         case Ast::SUPER_EXPRESSION:
  2156.             PutOp(OP_ALOAD_0); // must be use
  2157.             return 1;
  2158.         case Ast::PARENTHESIZED_EXPRESSION:
  2159.             {
  2160.             AstParenthesizedExpression * pe =
  2161.                     (AstParenthesizedExpression *) expression; 
  2162.             return EmitExpression(expression -> ParenthesizedExpressionCast() -> expression);
  2163.             }
  2164.         case Ast::CLASS_CREATION:
  2165.             return EmitClassInstanceCreationExpression((AstClassInstanceCreationExpression *)expression, 1);
  2166.         case Ast::ARRAY_CREATION:
  2167.             return EmitArrayCreationExpression((AstArrayCreationExpression *)expression);
  2168.         case Ast::DIM:
  2169.             return EmitExpression(expression -> DimExprCast() -> expression);
  2170.         case Ast::DOT:
  2171.         {
  2172.             AstFieldAccess * field_access =(AstFieldAccess *)expression;
  2173.             return ((field_access -> IsClassAccess()) && (field_access -> resolution_opt))
  2174.                                                        ? (ClassFile::type -> outermost_type -> ACC_INTERFACE()
  2175.                                                                     ? EmitExpression(field_access -> resolution_opt)
  2176.                                                                     : GenerateClassAccess(field_access))
  2177.                                                        : EmitFieldAccess(field_access);
  2178.         }
  2179.         case Ast::CALL:
  2180.             return EmitMethodInvocation((AstMethodInvocation *)expression, 0);
  2181.         case Ast::ARRAY_ACCESS:             // if seen alone this will be as RHS
  2182.             return EmitArrayAccessRHS((AstArrayAccess *) expression);
  2183.         case Ast::POST_UNARY:
  2184.             return EmitPostUnaryExpression((AstPostUnaryExpression *)expression,1);
  2185.         case Ast::PRE_UNARY:
  2186.             return EmitPreUnaryExpression((AstPreUnaryExpression *)expression,1);
  2187.         case Ast::CAST:
  2188.         {
  2189.           AstCastExpression * cast_expression = expression -> CastExpressionCast();
  2190.             if (cast_expression -> expression-> Type() -> Primitive())
  2191.             {
  2192.              // primitive types require casting
  2193.               return EmitCastExpression(cast_expression);
  2194.             }
  2195.             else {
  2196.               // not need to cast, just evaluate operand
  2197.                 return EmitExpression(cast_expression -> expression); 
  2198.             }
  2199.         }
  2200.  
  2201.         case Ast::CHECK_AND_CAST:
  2202.             return EmitCastExpression((AstCastExpression *)expression);
  2203.         case Ast::BINARY:
  2204.             return EmitBinaryExpression((AstBinaryExpression *)expression);
  2205.         case Ast::CONDITIONAL:
  2206.             return EmitConditionalExpression((AstConditionalExpression *)expression);
  2207.         case Ast::ASSIGNMENT:
  2208.             return EmitAssignmentExpression((AstAssignmentExpression *)expression,1);
  2209.         case Ast::NULL_LITERAL:
  2210.             PutOp(OP_ACONST_NULL);
  2211.             return 1;
  2212.         default:
  2213.             chaos("unknown expression kind");
  2214.             return 0; // even tho will not reach here
  2215.     }
  2216. }
  2217. void ByteCode::EmitArrayAccessLHS(AstArrayAccess *expression) 
  2218. {
  2219.     LoadReference(expression -> base);
  2220.     EmitExpression(expression -> expression);
  2221. }
  2222. int ByteCode::EmitArrayAccessRHS(AstArrayAccess *expression) 
  2223. {
  2224.     EmitArrayAccessLHS(expression); // get array address and index
  2225.     return LoadArrayElement(expression-> Type());
  2226. }
  2227.  
  2228. void ByteCode::EmitFieldAccessLHSBase(AstExpression * expression) {
  2229.     AstFieldAccess * field;
  2230.     AstSimpleName * simple_name;
  2231.     field = expression -> FieldAccessCast();
  2232.     if (field){
  2233.         if (field -> resolution_opt) {
  2234.            expression = field -> resolution_opt;
  2235.         }
  2236.     }
  2237.     else if (expression -> SimpleNameCast()) {
  2238.         simple_name = expression -> SimpleNameCast();
  2239.         if (simple_name -> resolution_opt) {
  2240.             expression = simple_name -> resolution_opt;
  2241.         }
  2242.     }
  2243.     VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
  2244.     field = expression -> FieldAccessCast();
  2245.     if (field){
  2246.         EmitExpression(field -> base);
  2247.     }
  2248.     else if (expression -> SimpleNameCast()) {
  2249.         PutOp(OP_ALOAD_0); // get address of "this"
  2250.     }
  2251.     else {
  2252.         chaos("unexpected AssignmentExpressionField operand base type");
  2253.     }
  2254. }
  2255.  
  2256. void ByteCode::EmitFieldAccessLHS(AstExpression * expression)
  2257. {
  2258.     EmitFieldAccessLHSBase(expression);
  2259.     PutOp(OP_DUP);     // save base address of field for later store
  2260.     PutOp(OP_GETFIELD);
  2261.     ChangeStack(this_control.IsDoubleWordType(expression-> Type()) ? 1: 0);
  2262.     PutU2(GenerateFieldReference((VariableSymbol *) expression -> symbol));
  2263. }
  2264. void ByteCode::GenerateClassAccessMethod(MethodSymbol * msym) {
  2265. // generate code for access method used to set class literal fields
  2266.     /* The code takes the form
  2267.         aload_0          load this
  2268.         invokestatic  java/lang/Class.forName(String)java/lang/Class
  2269.         areturn         return Class object for the class named by string
  2270.         // exception handler if forName fails
  2271.         astore_1        save exception
  2272.         new java.lang.NoClassDefFoundError
  2273.         dup             save so can return
  2274.         aload_1         recover exception
  2275.         invokevirtual java.lang.Throwable.getMessage() to get error message
  2276.         invokenonvirtual <init>     // invoke initializer
  2277.         athrow          rethrow the exception
  2278.     */
  2279.     
  2280.     code_attribute -> max_locals = 2;
  2281.     PutOp(OP_ALOAD_0);
  2282.     PutOp(OP_INVOKESTATIC);
  2283.     ChangeStack(-1);
  2284.     PutU2(BuildMethodref(RegisterClass(U8S_java_SL_lang_SL_Class, strlen(U8S_java_SL_lang_SL_Class)),
  2285.         BuildNameAndType(RegisterUtf8(U8S_forName, strlen(U8S_forName)),
  2286.                           RegisterUtf8(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_Ljava_SL_lang_SL_Class_SC,
  2287.                                         strlen(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_Ljava_SL_lang_SL_Class_SC)))));
  2288.     ChangeStack(1);
  2289.  
  2290.     PutOp(OP_ARETURN);
  2291.     PutOp(OP_ASTORE_1);
  2292.     PutOp(OP_NEW);
  2293.     PutU2(RegisterClass(U8S_java_SL_lang_SL_NoClassDefFoundError, strlen(U8S_java_SL_lang_SL_NoClassDefFoundError)));
  2294.     PutOp(OP_DUP);
  2295.     PutOp(OP_ALOAD_1);
  2296.     PutOp(OP_INVOKEVIRTUAL);
  2297.     ChangeStack(-1);
  2298.     PutU2(BuildMethodref(RegisterClass(U8S_java_SL_lang_SL_Throwable, strlen(U8S_java_SL_lang_SL_Throwable)),
  2299.         BuildNameAndType(
  2300.             RegisterUtf8(U8S_getMessage, strlen(U8S_getMessage)),
  2301.             RegisterUtf8(U8S_LP_RP_Ljava_SL_lang_SL_String_SC, strlen(U8S_LP_RP_Ljava_SL_lang_SL_String_SC)))));
  2302.     ChangeStack(1);
  2303.  
  2304.     PutOp(OP_INVOKENONVIRTUAL);
  2305.     ChangeStack(-1);
  2306.     PutU2(BuildMethodref(RegisterClass(U8S_java_SL_lang_SL_NoClassDefFoundError, strlen(U8S_java_SL_lang_SL_NoClassDefFoundError)),
  2307.          BuildNameAndType(
  2308.              RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_)),
  2309.              RegisterUtf8(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_V, strlen(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_V)))));
  2310.     ChangeStack(1);
  2311.     PutOp(OP_ATHROW);
  2312.     code_attribute -> max_stack = 3;
  2313.         int exception_index = code_attribute -> exception_table.NextIndex();
  2314.         code_attribute -> exception_table[exception_index].start_pc = 0;
  2315.         code_attribute -> exception_table[exception_index].end_pc = 5; // DS 11 feb
  2316.         code_attribute -> exception_table[exception_index].handler_pc = 5;
  2317.         code_attribute -> exception_table[exception_index].catch_type =
  2318.             RegisterClass(U8S_java_SL_lang_SL_ClassNotFoundException, strlen(U8S_java_SL_lang_SL_ClassNotFoundException));
  2319.         
  2320. }
  2321. int ByteCode::GenerateClassAccess(AstFieldAccess * field_access)
  2322. {  // here to generate code to dymanically initialize the field for a class literal and then return its value
  2323.     Label lab1,lab2;
  2324.     if (field_access -> symbol -> VariableCast()) {
  2325.         // simple case in immediate environment, can use field on both left and right
  2326.  
  2327.         //(TypeSymbol * type)
  2328.     // evaluate X.class literal. If X is a primitive type, this is a predefined field;
  2329.     // otherwise, we must create a new synthetic field to hold the desired result and
  2330.     // initialize it at runtime.
  2331.         /* generate
  2332.            getstatic class_field     load class field
  2333.            ifnull lab1               branch if not yet set
  2334.            get class_field           here if set, return value
  2335.            goto lab2
  2336.            lab1:                     here to initialize the field
  2337.            load class_constant       get name of class
  2338.            invokestatic              invoke generated method to get class_field  desired value
  2339.            dup                       save value so can return it
  2340.            put class_field           initialize the field
  2341.            lab2:
  2342.            */
  2343.         VariableSymbol * sym =  field_access -> symbol -> VariableCast();
  2344.  
  2345.         PutOp(OP_GETSTATIC);
  2346.         PutU2(GenerateFieldReference(sym));
  2347.         ChangeStack(1);
  2348.         EmitBranch(OP_IFNULL, lab1);
  2349.         PutOp(OP_GETSTATIC);
  2350.         PutU2(GenerateFieldReference(sym));
  2351.         ChangeStack(1);
  2352.         EmitBranch(OP_GOTO, lab2);
  2353.         DefineLabel(lab1);
  2354.         // generate load of constant naming the class
  2355.         LoadLiteral(field_access -> base-> Type() -> ClassLiteralName(), this_control.String());
  2356.         PutOp(OP_INVOKESTATIC);
  2357.         CompleteCall(class_literal_method, 1, 0);
  2358.         PutOp(OP_DUP);
  2359.         PutOp(OP_PUTSTATIC);
  2360.         PutU2(GenerateFieldReference(sym));
  2361.         ChangeStack(-1);
  2362.     }
  2363.     else {
  2364.         // here in nested case, where must invoke access methods for the field
  2365.         VariableSymbol * sym =  field_access -> symbol -> VariableCast();
  2366.         MethodSymbol * read_symbol = field_access -> symbol -> MethodCast();
  2367.         MethodSymbol * write_symbol = field_access -> resolution_opt -> symbol -> MethodCast();
  2368.  
  2369.         AstMethodInvocation * resolve = field_access -> resolution_opt -> MethodInvocationCast();
  2370.         u2 read_ref, write_ref;
  2371.         // need load this for class with method
  2372.         // if the next statement read field_access -> resolution_opt -> symbol = read_method, then
  2373.         // generating code for that expression tree would give us what we want
  2374.         field_access -> resolution_opt -> symbol = read_symbol;
  2375.         PutOp(OP_INVOKESTATIC);
  2376.         read_ref = BuildMethodref(RegisterClass(read_symbol -> containing_type -> fully_qualified_name),
  2377.             BuildNameAndType(
  2378.                 RegisterUtf8(read_symbol -> ExternalIdentity() -> Utf8_literal),
  2379.                 RegisterUtf8(read_symbol -> signature)));
  2380.         PutU2(read_ref);
  2381.         ChangeStack(1);
  2382.  
  2383.         EmitBranch(OP_IFNULL, lab1);
  2384.         PutOp(OP_INVOKESTATIC);
  2385.         PutU2(read_ref);
  2386.         ChangeStack(1);
  2387.         EmitBranch(OP_GOTO, lab2);
  2388.         DefineLabel(lab1);
  2389.         // generate load of constant naming the class
  2390.         LoadLiteral(field_access -> base-> Type() -> ClassLiteralName(), this_control.String());
  2391.         PutOp(OP_INVOKESTATIC);
  2392.         CompleteCall(class_literal_method, 1, 0);
  2393.         PutOp(OP_DUP);
  2394.         PutOp(OP_INVOKESTATIC);
  2395.         write_ref = BuildMethodref(RegisterClass(write_symbol -> containing_type -> fully_qualified_name),
  2396.             BuildNameAndType(
  2397.                 RegisterUtf8(write_symbol -> ExternalIdentity() -> Utf8_literal),
  2398.                 RegisterUtf8(write_symbol -> signature)));
  2399.         PutU2(write_ref);
  2400.         ChangeStack(-1); // to indicate argument popped
  2401.         
  2402.     }
  2403.     DefineLabel(lab2);
  2404.     CompleteLabel(lab1);
  2405.     CompleteLabel(lab2);
  2406.     return 1; // return one-word (reference) result
  2407. }
  2408.  
  2409. int ByteCode::EmitArrayCreationExpression(AstArrayCreationExpression *expression) 
  2410. {
  2411.     // see also OP_MULTINEWARRAY
  2412.     int dims;
  2413.     if (expression -> array_initializer_opt) {
  2414.         InitializeArray(expression-> Type(), expression -> array_initializer_opt);
  2415.     }
  2416.     else {
  2417.         dims = expression -> NumDimExprs();
  2418.         // need to push value of dimension(s)
  2419.         for (int i = 0;i < dims;i++) {
  2420.             AstDimExpr *d_expr = expression -> DimExpr(i);
  2421.             EmitExpression(d_expr -> expression);
  2422.         }
  2423.         EmitNewArray(dims, expression-> Type());
  2424.     }
  2425.     return 1;
  2426. }
  2427.  
  2428. int ByteCode::EmitAssignmentExpression(AstAssignmentExpression *expression,int need_value)
  2429. {
  2430.     // ASSIGNMENT
  2431.     int kind;
  2432.     int opc;
  2433.     int need_cast=0;
  2434.     VariableSymbol * sym;
  2435.     AstExpression * left_hand_side;
  2436.     TypeSymbol * expression_type = expression-> Type();
  2437.     TypeSymbol * expression_expression_type = expression -> expression-> Type();
  2438.     TypeSymbol * left_type;
  2439.     TypeSymbol * dest_type;
  2440.     TypeSymbol * cast_type;
  2441.     TypeSymbol * op_type;
  2442.     int stack_words = 0;
  2443.     if (expression -> left_hand_side -> CastExpressionCast()) {
  2444.         need_cast = 1;
  2445.         cast_type = expression -> left_hand_side -> CastExpressionCast()-> Type();
  2446.         left_hand_side = expression -> left_hand_side -> CastExpressionCast() -> expression;
  2447.         op_type = cast_type;
  2448.         dest_type = expression -> left_hand_side-> Type();;
  2449.     }
  2450.     else {
  2451.         left_hand_side = expression -> left_hand_side;
  2452.         op_type = expression_type;
  2453.     }
  2454.     left_type = left_hand_side-> Type();
  2455.     kind = GetLHSKind(expression -> left_hand_side, expression -> write_method);
  2456.     if (expression -> assignment_tag == AstAssignmentExpression::EQUAL) {
  2457.         switch(kind) {
  2458.             case LHS_ARRAY:
  2459.                 EmitArrayAccessLHS(left_hand_side -> ArrayAccessCast()); // lhs must be array access
  2460.                 break;
  2461.             case LHS_FIELD:
  2462.                 EmitFieldAccessLHSBase(left_hand_side); // load base for field access
  2463.                 break;
  2464.             case LHS_CLASS_METHOD:
  2465.                 // need to load address of object, obtained from resolution
  2466.                 ResolveAccess(left_hand_side, 0); // just get address
  2467.                 break;
  2468.             case LHS_STATIC_METHOD:
  2469.                 // nothing to do for static method at this point
  2470.                 break;
  2471.         }
  2472.         EmitExpression(expression -> expression);
  2473.     }
  2474.     else {
  2475.         // here for compound assignment. Get the left operand, saving any information necessary to
  2476.         // update its value on the stack below the value.
  2477.         switch(kind) {
  2478.             case LHS_ARRAY:
  2479.                 EmitArrayAccessLHS(left_hand_side -> ArrayAccessCast()); // lhs must be array access
  2480.                 PutOp(OP_DUP2); // save base and index for later store
  2481.                 // load current value
  2482.                 (void) LoadArrayElement(expression_type);
  2483.                 break;
  2484.             case LHS_FIELD:
  2485.                 EmitFieldAccessLHS(left_hand_side);
  2486.                 break;
  2487.             case LHS_LOCAL:
  2488.             case LHS_STATIC:
  2489.                 (void) LoadSimple(kind,left_hand_side);
  2490.                 ChangeStack(this_control.IsDoubleWordType(left_type) ? 1: 0); // CHECK_THIS? Is this really necessary
  2491.                 break;
  2492.             case LHS_CLASS_METHOD:
  2493.                 // need to load address of object, obtained from resolution, saving a copy on the stack
  2494.                 ResolveAccess(left_hand_side, 1); // get address and value
  2495.                 break;
  2496.             case LHS_STATIC_METHOD:
  2497.                 // get value by invoking the appropriate resolution
  2498.                 EmitExpression(left_hand_side -> SimpleNameCast() -> resolution_opt); // get value
  2499.                 break;
  2500.         }
  2501.  
  2502.         if (expression -> assignment_tag ==AstAssignmentExpression::PLUS_EQUAL
  2503.             && left_type == this_control.String()) {
  2504.             // Here for string concatenation.
  2505.             EmitStringBuffer();
  2506.             PutOp(OP_SWAP);    // swap address if buffer and string to update.
  2507.             EmitStringAppendMethod(this_control.String());
  2508.             AppendString(expression -> expression);
  2509.             EmitCallStringToString();
  2510.         }
  2511.         else {
  2512.             // Here for operation other than string concatenation. Determine the opcode to use.
  2513.             if (this_control.IsSimpleIntegerValueType(op_type)||
  2514.                 op_type == this_control.boolean_type){
  2515.                 switch (expression -> assignment_tag) {
  2516.                     case AstAssignmentExpression::STAR_EQUAL:                  opc = OP_IMUL;  break;
  2517.                     case AstAssignmentExpression::SLASH_EQUAL:                 opc = OP_IDIV;  break;
  2518.                     case AstAssignmentExpression::MOD_EQUAL:                   opc = OP_IREM;  break;
  2519.                     case AstAssignmentExpression::PLUS_EQUAL:                  opc = OP_IADD;  break;
  2520.                     case AstAssignmentExpression::MINUS_EQUAL:                 opc = OP_ISUB;  break;
  2521.                     case AstAssignmentExpression::LEFT_SHIFT_EQUAL:            opc = OP_ISHL;  break;
  2522.                     case AstAssignmentExpression::RIGHT_SHIFT_EQUAL:           opc = OP_ISHR;  break;
  2523.                     case AstAssignmentExpression::UNSIGNED_RIGHT_SHIFT_EQUAL:  opc = OP_IUSHR; break;
  2524.                     case AstAssignmentExpression::AND_EQUAL:                   opc = OP_IAND;  break;
  2525.                     case AstAssignmentExpression::IOR_EQUAL:                   opc = OP_IOR;   break;
  2526.                     case AstAssignmentExpression::XOR_EQUAL:                   opc = OP_IXOR;  break;
  2527.                 }
  2528.             }
  2529.             else if (op_type == this_control.long_type){
  2530.                 switch (expression -> assignment_tag) {
  2531.                     case AstAssignmentExpression::STAR_EQUAL:                  opc = OP_LMUL;  break;
  2532.                     case AstAssignmentExpression::SLASH_EQUAL:                 opc = OP_LDIV;  break;
  2533.                     case AstAssignmentExpression::MOD_EQUAL:                   opc = OP_LREM;  break;
  2534.                     case AstAssignmentExpression::PLUS_EQUAL:                  opc = OP_LADD;  break;
  2535.                     case AstAssignmentExpression::MINUS_EQUAL:                 opc = OP_LSUB;  break;
  2536.                     case AstAssignmentExpression::LEFT_SHIFT_EQUAL:            opc = OP_LSHL;  break;
  2537.                     case AstAssignmentExpression::RIGHT_SHIFT_EQUAL:           opc = OP_LSHR;  break;
  2538.                     case AstAssignmentExpression::UNSIGNED_RIGHT_SHIFT_EQUAL:  opc = OP_LUSHR; break;
  2539.                     case AstAssignmentExpression::AND_EQUAL:                   opc = OP_LAND;  break;
  2540.                     case AstAssignmentExpression::IOR_EQUAL:                   opc = OP_LOR;   break;
  2541.                     case AstAssignmentExpression::XOR_EQUAL:                   opc = OP_LXOR;  break;
  2542.                 }
  2543.             }
  2544.             else if (op_type == this_control.float_type) {
  2545.                 switch (expression -> assignment_tag) {
  2546.                     case AstAssignmentExpression::STAR_EQUAL:                  opc = OP_FMUL;  break;
  2547.                     case AstAssignmentExpression::SLASH_EQUAL:                 opc = OP_FDIV;  break;
  2548.                     case AstAssignmentExpression::MOD_EQUAL:                   opc = OP_FREM;  break;
  2549.                     case AstAssignmentExpression::PLUS_EQUAL:                  opc = OP_FADD;  break;
  2550.                     case AstAssignmentExpression::MINUS_EQUAL:                 opc = OP_FSUB;  break;
  2551.                 }
  2552.             }
  2553.             else if (op_type == this_control.double_type)    {
  2554.                 switch (expression -> assignment_tag) {
  2555.                     case AstAssignmentExpression::STAR_EQUAL:                  opc = OP_DMUL;  break;
  2556.                     case AstAssignmentExpression::SLASH_EQUAL:                 opc = OP_DDIV;  break;
  2557.                     case AstAssignmentExpression::MOD_EQUAL:                   opc = OP_DREM;  break;
  2558.                     case AstAssignmentExpression::PLUS_EQUAL:                  opc = OP_DADD;  break;
  2559.                     case AstAssignmentExpression::MINUS_EQUAL:                 opc = OP_DSUB;  break;
  2560.                 }
  2561.             }
  2562.  
  2563.             // convert value to desired type if necessary
  2564.             if (need_cast) {
  2565.                 EmitCast(cast_type,left_type);
  2566.             }
  2567.  
  2568.             EmitExpression(expression -> expression);
  2569.  
  2570.             PutOp(opc);  
  2571.  
  2572.             if (need_cast) { // now cast result back to type of result
  2573.                 EmitCast(left_type, cast_type);
  2574.             }
  2575.         }
  2576.     }
  2577.     // Update left operand, saving value of right operand if it is needed.
  2578.     switch(kind) {
  2579.         case LHS_ARRAY:
  2580.             if (need_value) {
  2581.                 if (this_control.IsDoubleWordType(left_type)) {
  2582.                     PutOp(OP_DUP2_X2);
  2583.                 }
  2584.                 else PutOp(OP_DUP_X2);
  2585.             }
  2586.             StoreArrayElement(expression_type);
  2587.             break;
  2588.         case LHS_FIELD:
  2589.         case LHS_CLASS_METHOD:
  2590.             if (need_value) {
  2591.                 if (this_control.IsDoubleWordType(left_type)) {
  2592.                     PutOp(OP_DUP2_X1);
  2593.                 }
  2594.                 else PutOp(OP_DUP_X1);
  2595.             }
  2596.             if (kind==LHS_CLASS_METHOD) {
  2597.                 stack_words = this_control.IsDoubleWordType(left_type) ? 2: 1;
  2598.                 PutOp(OP_INVOKEVIRTUAL);
  2599.                 CompleteCall(expression -> write_method, stack_words, 0);
  2600.             }
  2601.             else {
  2602.                 StoreField(left_hand_side);
  2603.             }
  2604.             break;
  2605.         case LHS_LOCAL:
  2606.         case LHS_STATIC:
  2607.         case LHS_STATIC_METHOD:
  2608.             if (need_value) {
  2609.                 if (this_control.IsDoubleWordType(left_type)) {
  2610.                     PutOp(OP_DUP2);
  2611.                 }
  2612.                 else PutOp(OP_DUP);
  2613.             }
  2614.             if (kind==LHS_STATIC_METHOD) {
  2615.                 stack_words = this_control.IsDoubleWordType(left_type) ? 2: 1;
  2616.                 PutOp(OP_INVOKESTATIC);
  2617.                 CompleteCall(expression -> write_method, stack_words, 0);
  2618.             }
  2619.             else {
  2620.                 StoreSimple(kind,left_hand_side);
  2621.             }
  2622.  
  2623.             break;
  2624.     }
  2625.     return GetTypeWords(expression_type);
  2626. }
  2627.  
  2628. // Similar code patterns are used for the ordered comparisons
  2629. int ByteCode::EmitBinaryExpression(AstBinaryExpression *expression) 
  2630. {
  2631.     // BINARY
  2632.     switch (expression -> binary_tag) { // process boolean-results first
  2633.         case AstBinaryExpression::OR_OR:
  2634.         case AstBinaryExpression::AND_AND:
  2635.         case AstBinaryExpression::LESS:
  2636.         case AstBinaryExpression::LESS_EQUAL:
  2637.         case AstBinaryExpression::GREATER:
  2638.         case AstBinaryExpression::GREATER_EQUAL:
  2639.         case AstBinaryExpression::EQUAL_EQUAL:
  2640.         case AstBinaryExpression::NOT_EQUAL: {
  2641.             Label lab1,lab2;
  2642.             EmitBranchIfExpression(expression,true,lab1);
  2643.             PutOp(OP_ICONST_0);                // push false
  2644.             EmitBranch(OP_GOTO,lab2);
  2645.             DefineLabel(lab1);
  2646.             PutOp(OP_ICONST_1);                // push false
  2647.             DefineLabel(lab2);
  2648.             CompleteLabel(lab1);
  2649.             CompleteLabel(lab2);
  2650.         }
  2651.         return 1;
  2652.     }
  2653.     if (expression -> binary_tag == AstBinaryExpression::INSTANCEOF) {
  2654.         TypeSymbol * instanceof_type = expression -> right_expression-> Type();
  2655.         EmitExpression(expression -> left_expression);
  2656.         PutOp(OP_INSTANCEOF);
  2657.         if (instanceof_type -> num_dimensions) {
  2658.             PutU2(RegisterClass(instanceof_type -> signature));
  2659.         }
  2660.         else {
  2661.             PutU2(RegisterClass(instanceof_type -> fully_qualified_name));
  2662.         }
  2663.         return 1;
  2664.     }
  2665.     // special case string concatenation
  2666.     if (expression -> binary_tag == AstBinaryExpression::PLUS && (IsReferenceType(expression -> left_expression-> Type())) ||
  2667.         IsReferenceType(expression -> right_expression-> Type())) {
  2668.         ConcatenateString(expression);
  2669.         return 1;
  2670.     }
  2671. #ifdef TBSL
  2672.     // debug this later (DS 19 nov 96)
  2673.     // try to simplify if one operand known to be zero.
  2674.     if (isZero(expression -> left_expression)) {
  2675.         TypeSymbol * right_type = expression -> right_expression-> Type();
  2676.         switch (expression -> binary_tag) {
  2677.             case AstBinaryExpression::PLUS:
  2678.             case AstBinaryExpression::IOR:
  2679.             case AstBinaryExpression::XOR:
  2680.                     // here for cases that simplify to the right operand
  2681.                     EmitExpression(expression -> right_expression);
  2682.             return;
  2683.             case AstBinaryExpression::STAR:
  2684.             case AstBinaryExpression::AND:
  2685.             case AstBinaryExpression::LEFT_SHIFT:
  2686.             case AstBinaryExpression::RIGHT_SHIFT:
  2687.             case AstBinaryExpression::UNSIGNED_RIGHT_SHIFT:
  2688.                     // here for cases that evaluate to zero
  2689.                     if (this_control.IsSimpleIntegerValueType(right_type)) {
  2690.                 LoadShort(0);
  2691.             }
  2692.                     else if (right_type == this_control.long_type) {
  2693.                         PutOp(OP_LCONST_0);
  2694.                     }
  2695.                     else if (right_type == this_control.float_type) {
  2696.                         PutOp(OP_FCONST_0);
  2697.                     }
  2698.                     else if (right_type == this_control.double_type) {
  2699.                         PutOp(OP_DCONST_0);
  2700.                     }
  2701.                     else chaos("unexpected type in expression simplification");
  2702.                     return GetTypeWords(right_type);
  2703.  
  2704.             case AstBinaryExpression::MINUS:
  2705.                     // 0 - x is negation of x
  2706.                     EmitExpression(expression -> right_expression);
  2707.             if (this_control.IsSimpleIntegerValueType(right_type)) {
  2708.                 PutOp(OP_INEG);    
  2709.             }
  2710.             else if (right_type == this_control.long_type) {
  2711.                 PutOp(OP_LNEG);
  2712.             }
  2713.             else if (right_type == this_control.float_type) {
  2714.                 PutOp(OP_FNEG);
  2715.             }
  2716.             else if (right_type == this_control.double_type) {
  2717.                 PutOp(OP_DNEG);
  2718.             }
  2719.             else chaos("unexpected type in expression simplification");
  2720.             return 1;
  2721.         }
  2722.     }
  2723.  
  2724.  
  2725.     if (isZero(expression -> right_expression)) {
  2726.         TypeSymbol * left_type = expression -> left_expression-> Type();
  2727.         switch (expression->binary_tag) {
  2728.             case AstBinaryExpression::PLUS:
  2729.             case AstBinaryExpression::MINUS:
  2730.             case AstBinaryExpression::IOR:
  2731.             case AstBinaryExpression::XOR:
  2732.             case AstBinaryExpression::LEFT_SHIFT:
  2733.             case AstBinaryExpression::RIGHT_SHIFT:
  2734.             case AstBinaryExpression::UNSIGNED_RIGHT_SHIFT:
  2735.                     // here for cases that simplify to the left operand
  2736.                     EmitExpression(expression->left_expression);
  2737.             return;
  2738.             case AstBinaryExpression::STAR:
  2739.             case AstBinaryExpression::AND:
  2740.                     // here for cases that evaluate to zero
  2741.                     if (this_control.IsSimpleIntegerValueType(left_type)) {
  2742.                 LoadShort(0);
  2743.             }
  2744.                     else if (left_type == this_control.long_type) {
  2745.                         PutOp(OP_LCONST_0);
  2746.                     }
  2747.                     else if (left_type == this_control.float_type) {
  2748.                         PutOp(OP_FCONST_0);
  2749.                     }
  2750.                     else if (left_type == this_control.double_type) {
  2751.                         PutOp(OP_DCONST_0);
  2752.                     }
  2753.                     else chaos("unexpected type in expression simplification");
  2754.                     return;
  2755.         }
  2756.  
  2757.     }
  2758. #endif
  2759.  
  2760.     EmitExpression(expression -> left_expression);
  2761.     EmitExpression(expression -> right_expression);
  2762.  
  2763.     switch (expression -> binary_tag) {
  2764.         case AstBinaryExpression::STAR:
  2765.                 EmitBinaryOp(expression, OP_IMUL, OP_LMUL, OP_FMUL, OP_DMUL);
  2766.         break;
  2767.         case AstBinaryExpression::SLASH:
  2768.                 EmitBinaryOp(expression, OP_IDIV, OP_LDIV, OP_FDIV, OP_DDIV);
  2769.         break;
  2770.         case AstBinaryExpression::MOD:
  2771.                 EmitBinaryOp(expression, OP_IREM, OP_LREM, OP_FREM, OP_DREM);
  2772.         break;
  2773.         case AstBinaryExpression::PLUS:
  2774.                 EmitBinaryOp(expression, OP_IADD, OP_LADD, OP_FADD, OP_DADD);
  2775.         break;
  2776.         case AstBinaryExpression::MINUS:
  2777.                 EmitBinaryOp(expression, OP_ISUB, OP_LSUB, OP_FSUB, OP_DSUB);
  2778.         break;
  2779.         case AstBinaryExpression::LEFT_SHIFT:
  2780.                 EmitBinaryOp(expression, OP_ISHL, OP_LSHL, 0, 0);
  2781.                 break;
  2782.         case AstBinaryExpression::RIGHT_SHIFT:
  2783.                 EmitBinaryOp(expression, OP_ISHR, OP_LSHR, 0, 0);
  2784.                 break;
  2785.         case AstBinaryExpression::UNSIGNED_RIGHT_SHIFT:
  2786.                 EmitBinaryOp(expression, OP_IUSHR, OP_LUSHR, 0, 0);
  2787.                 break;
  2788.                 //          case AstBinaryExpression::INSTANCEOF:
  2789.                 //              EmitInstanceofExpression((AstInstanceofExpression *)expression);
  2790.                 //              break;
  2791.         case AstBinaryExpression::AND:
  2792.                 EmitBinaryOp(expression, OP_IAND, OP_LAND, 0, 0);
  2793.         break;
  2794.         case AstBinaryExpression::XOR:
  2795.                 EmitBinaryOp(expression, OP_IXOR, OP_LXOR, 0, 0);
  2796.         break;
  2797.         case AstBinaryExpression::IOR:
  2798.                 EmitBinaryOp(expression, OP_IOR, OP_LOR, 0, 0);
  2799.         break;
  2800.         default:
  2801.             chaos("binary unknown tag");
  2802.     }
  2803.     return GetTypeWords(expression-> Type());
  2804. }
  2805.  
  2806.  
  2807. void ByteCode::EmitBinaryOp(AstBinaryExpression *expression, int iop, int lop, int fop, int dop)
  2808. {
  2809.     int opc = 0;
  2810.     TypeSymbol * type = expression -> left_expression-> Type();
  2811.     // binary  PutOp
  2812.     if (this_control.IsSimpleIntegerValueType(type)
  2813.         || type == this_control.boolean_type)        opc = iop;
  2814.     else if (type == this_control.long_type)         opc = lop;
  2815.     else if (type == this_control.float_type)        opc = fop;
  2816.     else if (type == this_control.double_type)       opc = dop;
  2817.     if (opc == 0)       chaos(" * undefined on this type");
  2818.     PutOp(opc);
  2819.  
  2820. }   
  2821. int ByteCode::EmitCastExpression(AstCastExpression *expression) {
  2822.     TypeSymbol * dest_type = expression-> Type();
  2823.     TypeSymbol * source_type = expression -> expression-> Type();
  2824.     // convert from numeric type src to destination type dest
  2825.     EmitExpression(expression -> expression); 
  2826.     EmitCast(dest_type,source_type);
  2827.     return GetTypeWords(dest_type);
  2828. }
  2829. void ByteCode::EmitCast(TypeSymbol * dest_type, TypeSymbol * source_type)
  2830. {
  2831.     if (dest_type == source_type) return;  // done if nothing to do
  2832.     if (this_control.IsSimpleIntegerValueType(source_type)) {
  2833.         if (dest_type == this_control.long_type)         PutOp(OP_I2L);
  2834.         else if (dest_type == this_control.float_type)   PutOp(OP_I2F);
  2835.         else if (dest_type == this_control.double_type)  PutOp(OP_I2D);
  2836.         else if (dest_type == this_control.char_type)    PutOp(OP_I2C);
  2837.         else if (dest_type == this_control.byte_type)    PutOp(OP_I2B);
  2838.         else if (dest_type == this_control.short_type)   PutOp(OP_I2S);
  2839.         else if (dest_type == this_control.int_type); // no conversion needed
  2840.         else chaos("unsupported conversion");
  2841.     }
  2842.     else if (source_type == this_control.long_type) {
  2843.         if (this_control.IsSimpleIntegerValueType(dest_type)) {
  2844.           PutOp(OP_L2I);
  2845.           if (dest_type == this_control.char_type)   PutOp(OP_I2C);
  2846.           else if (dest_type == this_control.byte_type)  PutOp(OP_I2B);
  2847.           else if (dest_type == this_control.short_type) PutOp(OP_I2S);
  2848.             }
  2849.         else if (dest_type == this_control.float_type)   PutOp(OP_L2F);
  2850.         else if (dest_type == this_control.double_type)  PutOp(OP_L2D);
  2851.         else chaos("unsupported conversion");
  2852.     }
  2853.     else if (source_type == this_control.float_type) {
  2854.         if (this_control.IsSimpleIntegerValueType(dest_type)) {
  2855.           PutOp(OP_F2I);
  2856.           if (dest_type == this_control.char_type)   PutOp(OP_I2C);
  2857.           else if (dest_type == this_control.byte_type)  PutOp(OP_I2B);
  2858.           else if (dest_type == this_control.short_type) PutOp(OP_I2S);
  2859.         }
  2860.  
  2861.         else if (dest_type == this_control.long_type)    PutOp(OP_F2L);
  2862.         else if (dest_type == this_control.double_type)  PutOp(OP_F2D);
  2863.         else chaos("unsupported conversion");
  2864.     }
  2865.     else if (source_type == this_control.double_type) {
  2866.         if (this_control.IsSimpleIntegerValueType(dest_type)) {
  2867.           PutOp(OP_D2I);
  2868.           if (dest_type == this_control.char_type)   PutOp(OP_I2C);
  2869.           else if (dest_type == this_control.byte_type)  PutOp(OP_I2B);
  2870.           else if (dest_type == this_control.short_type) PutOp(OP_I2S);
  2871.         }
  2872.         else if (dest_type == this_control.long_type)    PutOp(OP_D2L);
  2873.         else if (dest_type == this_control.float_type)   PutOp(OP_D2F);
  2874.         else chaos("unsupported conversion");
  2875.     }
  2876.     else if (source_type == this_control.null_type) {
  2877.         //op(OP_ACONST_NULL);
  2878.     }
  2879.     else { // generate check cast instruction
  2880.     // it is possible to evaluate many of these at compile time
  2881.     if (dest_type -> num_dimensions) {
  2882.     PutOp(OP_CHECKCAST);
  2883.       PutU2(RegisterClass(dest_type -> signature)); 
  2884.     }
  2885.     else {
  2886.     PutOp(OP_CHECKCAST);
  2887.       PutU2(RegisterClass(dest_type -> fully_qualified_name));
  2888.     }
  2889.     }
  2890. }
  2891.     
  2892. int ByteCode::EmitClassInstanceCreationExpression(AstClassInstanceCreationExpression *expression, int need_value) 
  2893. {
  2894.     MethodSymbol * constructor = (MethodSymbol *) expression -> class_type -> symbol;
  2895.     TypeSymbol * type =  expression-> Type();
  2896.     int stack_words = 0;
  2897.     Label lab1;
  2898.     PutOp(OP_NEW);
  2899.     PutU2(RegisterClass(type -> fully_qualified_name));
  2900.     if (need_value) PutOp(OP_DUP); // save address of new object for constructor
  2901.     // call constructor
  2902.     // pass address of object explicitly passed to new if specified.
  2903.     if (expression -> base_opt) {
  2904.         stack_words += EmitExpression(expression -> base_opt);
  2905.         PutOp(OP_DUP);
  2906.         EmitBranch(OP_IFNONNULL, lab1);
  2907.         // need to test for null, raising NullPointerException if so. So just do athrow
  2908.         PutOp(OP_ACONST_NULL);
  2909.         PutOp(OP_ATHROW); 
  2910.         DefineLabel(lab1);
  2911.         CompleteLabel(lab1);
  2912.     }
  2913.  
  2914.     for (int i=0; i < expression -> NumLocalArguments();i++) {
  2915.         stack_words += EmitExpression((AstExpression *) expression -> LocalArgument(i));
  2916.     }
  2917.     for (int k=0; k < expression -> NumArguments();k++) {
  2918.         stack_words += EmitExpression((AstExpression *) expression -> Argument(k));
  2919.     }
  2920.     PutOp(OP_INVOKENONVIRTUAL);
  2921.     ChangeStack(-stack_words); 
  2922.     if (constructor -> constant_pool_index == 0 || constructor -> constant_pool_class!=class_id) { // build method ref for method
  2923.         constructor -> constant_pool_index = BuildMethodref(
  2924.             RegisterClass(type -> fully_qualified_name),
  2925.             BuildNameAndType(
  2926.                 RegisterUtf8(this_control.init_name_symbol -> Utf8_literal),
  2927.                 RegisterUtf8(constructor -> signature)));
  2928.         constructor -> constant_pool_class = class_id;
  2929.         }
  2930.     
  2931.     PutU2(constructor -> constant_pool_index);
  2932.     return 1;
  2933. }
  2934.  
  2935. int ByteCode::EmitConditionalExpression(AstConditionalExpression *expression)
  2936. {
  2937.     Label lab1,lab2;
  2938.     EmitBranchIfExpression(expression -> test_expression, false, lab1);
  2939.     EmitExpression(expression -> true_expression);
  2940.     EmitBranch(OP_GOTO,lab2);
  2941.     DefineLabel(lab1);
  2942.     EmitExpression(expression -> false_expression);
  2943.     DefineLabel(lab2);
  2944.     CompleteLabel(lab1);
  2945.     CompleteLabel(lab2);
  2946.     return GetTypeWords(expression -> true_expression-> Type());
  2947. }
  2948.  
  2949. int ByteCode::EmitFieldAccess(AstFieldAccess *expression) 
  2950. {
  2951.     AstExpression * p = expression -> base;
  2952.     VariableSymbol * sym =  expression -> symbol -> VariableCast();
  2953.     TypeSymbol * expression_type = expression-> Type();
  2954.     if (expression -> IsConstant()) {
  2955.             if (sym -> ACC_STATIC()) {
  2956.             if (!( p -> symbol -> TypeCast() || p -> symbol -> VariableCast())) {
  2957.               EmitExpression(p);
  2958.               PutOp(OP_POP);
  2959.             }
  2960.             }
  2961.         return LoadConstant(expression);
  2962.     }
  2963.     if (expression -> resolution_opt) {  // resolve reference to private field in parent
  2964.         return EmitExpression(expression -> resolution_opt);
  2965.     }
  2966.     if (p-> Type() -> IsArray() && sym -> ExternalIdentity() == this_control.length_name_symbol){
  2967.         EmitExpression(p);
  2968.         PutOp(OP_ARRAYLENGTH);
  2969.         return 1;
  2970.     }
  2971.     if (sym -> ACC_STATIC()) {
  2972.         if (!( p -> symbol -> TypeCast() || p -> symbol -> VariableCast())) {
  2973.           EmitExpression(p);
  2974.           PutOp(OP_POP);
  2975.         }
  2976.         PutOp(OP_GETSTATIC);
  2977.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? 2: 1);
  2978.     }
  2979.     else {
  2980.         EmitExpression(p); // get base
  2981.         PutOp(OP_GETFIELD);
  2982.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? 1: 0);
  2983.     }
  2984.     PutU2(GenerateFieldReference(sym));
  2985.     return GetTypeWords(expression_type);
  2986. }
  2987.  
  2988. void ByteCode::EmitCloneArray(AstMethodInvocation *expression)
  2989. {
  2990.     // generate code corresponding to
  2991.     //  try {
  2992.     //      evaluate super.clone();
  2993.     //  } catch (CloneNotSupportedException e) {
  2994.     //      throw new InternalError(e.getMessage());
  2995.     //  }
  2996.     MethodSymbol * msym = (MethodSymbol *) expression -> symbol;
  2997.     TypeSymbol * res_type = expression-> Type(); // result type
  2998.     AstFieldAccess * field;
  2999.     int start_pc,end_pc;
  3000.     Label end_label;
  3001.     int exception_index;
  3002.     // msym is clone_name_symbol, indicating array clone
  3003.     // use clone() in java/lang/Object.
  3004.     start_pc = code_attribute -> code.Length(); 
  3005.     field = expression -> method -> FieldAccessCast();
  3006.     if (field) {
  3007.         EmitExpression(field -> base);
  3008.     }
  3009.     else {
  3010.         chaos("field access expected in array clone");
  3011.     }
  3012.     PutOp(OP_INVOKEVIRTUAL);
  3013.     //  ChangeStack(-stack_words);
  3014.     PutU2(RegisterMethod(METHOD_CLONE));
  3015.     EmitBranch(OP_GOTO, end_label);
  3016.     end_pc = code_attribute -> code.Length(); 
  3017.     // indicate that we use at least 2 local variables (this and the exception)
  3018.     if (code_attribute -> max_locals < 2)
  3019.       code_attribute -> max_locals = 2; // CSA fix 08-dec-1998 for PR 294
  3020.     // start handler
  3021.     // can't count next StoreLocal as pop since in handler
  3022.     ChangeStack(1); 
  3023.     StoreLocal(1, this_control.Object());
  3024.     PutOp(OP_NEW); 
  3025.     PutU2(RegisterClass(U8S_java_SL_lang_SL_InternalError, strlen(U8S_java_SL_lang_SL_InternalError)));
  3026.     PutOp(OP_DUP);
  3027.     LoadLocal(1, this_control.Object());
  3028.     PutOp(OP_INVOKEVIRTUAL);
  3029.     PutU2(RegisterMethod(METHOD_CLONE_GETMESSAGE));
  3030.     PutOp(OP_INVOKENONVIRTUAL);
  3031.     PutU2(RegisterMethod(METHOD_CLONE_INIT));
  3032.     PutOp(OP_ATHROW);
  3033.     DefineLabel(end_label);
  3034.     CompleteLabel(end_label);
  3035.  
  3036.     exception_index = code_attribute -> exception_table.NextIndex();
  3037.     code_attribute -> exception_table[exception_index].start_pc = start_pc;
  3038.     code_attribute -> exception_table[exception_index].end_pc = end_pc;
  3039.     code_attribute -> exception_table[exception_index].handler_pc = end_pc;
  3040.     // "java/lang/CloneNotSupportedException"
  3041.     code_attribute -> exception_table[exception_index].catch_type =
  3042.         RegisterClass(U8S_java_SL_lang_SL_CloneNotSupportedException, strlen(U8S_java_SL_lang_SL_CloneNotSupportedException));
  3043.  
  3044. }
  3045.  
  3046. int ByteCode::EmitMethodInvocation(AstMethodInvocation *expression, int copy_base) 
  3047. {
  3048.     MethodSymbol * msym = (MethodSymbol *) expression -> symbol;
  3049.     AstSimpleName * simple_name;
  3050.     TypeSymbol * res_type = expression-> Type(); // result type
  3051.     int is_private = msym -> ACC_PRIVATE();
  3052.     int is_static = msym -> ACC_STATIC();
  3053.     int is_super=0; // set if super call
  3054.     int is_interface = msym -> containing_type -> ACC_INTERFACE();
  3055.     AstFieldAccess * field;
  3056.     int stack_words = 0; // words on stack needed for arguments
  3057.     if (msym -> ExternalIdentity() == this_control.clone_name_symbol) {
  3058.         if (msym -> containing_type -> IsArray()) {
  3059.             EmitCloneArray(expression);
  3060.             return GetTypeWords(res_type);
  3061.         }
  3062. #ifdef TBSL
  3063.         else {
  3064.            chaos(" clone not yet supported");
  3065.         }
  3066. #endif
  3067.     }
  3068.     if (is_static) {
  3069.        if (expression -> method -> FieldAccessCast()) {
  3070.            field = expression -> method -> FieldAccessCast();
  3071.            if (field -> base -> MethodInvocationCast()) {
  3072.               (void) EmitMethodInvocation(field -> base -> MethodInvocationCast(), 0);
  3073.               PutOp(OP_POP); // discard value (only evaluating for side effect)
  3074.            }
  3075.     
  3076.        }
  3077.     }
  3078.     else {
  3079.        field = expression -> method -> FieldAccessCast();
  3080.        if (field) {
  3081.          AstFieldAccess *sub_field_access = field -> base -> FieldAccessCast();
  3082.  
  3083.          if (field -> base -> SuperExpressionCast() || (sub_field_access && sub_field_access -> IsSuperAccess())) {
  3084.            is_super=1;
  3085.          }
  3086.          if (field -> base -> MethodInvocationCast()) {
  3087.              (void) EmitMethodInvocation(field -> base -> MethodInvocationCast(), 0);
  3088.          }
  3089.          else {
  3090.            EmitExpression(field -> base);
  3091.          }
  3092.        }
  3093.        else if (expression -> method -> SimpleNameCast()) {
  3094.            simple_name = expression -> method -> SimpleNameCast();
  3095.            if (simple_name -> resolution_opt) {  // use resolution if available
  3096.                (void) EmitExpression(simple_name -> resolution_opt);
  3097.            }
  3098.            else {
  3099.                // must be field of current object, so load this
  3100.                PutOp(OP_ALOAD_0);
  3101.            }
  3102.        }
  3103.        else {
  3104.           chaos("unexpected argument to field access");
  3105.        }
  3106.  
  3107.     }
  3108.     if (!is_static && copy_base) { // if need to save object ref for method invocation
  3109.         PutOp(OP_DUP);
  3110.     }
  3111.     for (int i=0; i < expression -> NumArguments();i++) {
  3112.         stack_words += EmitExpression((AstExpression *) expression -> Argument(i));
  3113.     }
  3114.     PutOp(msym -> ACC_STATIC() ? OP_INVOKESTATIC 
  3115.          : (is_super | is_private)  ? OP_INVOKENONVIRTUAL
  3116.          : is_interface ? OP_INVOKEINTERFACE 
  3117.          : OP_INVOKEVIRTUAL);
  3118.      CompleteCall(msym,stack_words, is_interface);
  3119.     return GetTypeWords(res_type);
  3120. }
  3121. void ByteCode::CompleteCall(MethodSymbol * msym,int stack_words, int is_interface)
  3122. {
  3123.     TypeSymbol * res_type = msym-> Type();
  3124.     ChangeStack(-stack_words);
  3125.     // need to get method index, the constant_pool index for a
  3126.     // reference to this method (a Methodref);
  3127.     if (msym -> constant_pool_index == 0 || msym -> constant_pool_class != class_id) { // build method ref for method
  3128.         if (is_interface) {
  3129.         msym -> constant_pool_index = BuildInterfaceMethodref(
  3130.             RegisterClass(msym -> containing_type -> fully_qualified_name),
  3131.             BuildNameAndType(
  3132.                 RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
  3133.                 RegisterUtf8(msym -> signature)));
  3134.         msym -> constant_pool_class = class_id;
  3135.         }
  3136.     else {
  3137.  
  3138.         msym -> constant_pool_index = BuildMethodref(
  3139.             RegisterClass(msym -> containing_type -> fully_qualified_name),
  3140.             BuildNameAndType(
  3141.                 RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
  3142.                 RegisterUtf8(msym -> signature)));
  3143.         msym -> constant_pool_class = class_id;
  3144.         }
  3145.     }
  3146.     
  3147.     PutU2(msym -> constant_pool_index);
  3148.     if (is_interface) {
  3149.       PutU1(stack_words+1);
  3150.       PutU1(0);
  3151.     }
  3152.     // must account for value returned by method. Assume it places one
  3153.     // word on stack and correct this assumption if wrong.
  3154.     stack_words=1;
  3155.     if (this_control.IsDoubleWordType(res_type)) {
  3156.         stack_words = 2;
  3157.     }
  3158.     else if (res_type == this_control.void_type) { // no return value
  3159.         stack_words = 0;
  3160.     }
  3161.     ChangeStack(stack_words);
  3162. }   
  3163.  
  3164. void ByteCode::EmitNewArray(int dims,TypeSymbol * type)
  3165. {
  3166.     int i;
  3167.     TypeSymbol * element_type = type -> ArraySubtype();
  3168.  
  3169.     if (dims==0 || (dims == 1 && type -> num_dimensions == dims)) {
  3170.         if (this_control.IsNumeric(element_type) || element_type == this_control.boolean_type) {
  3171.             // if one-dimensional primitive
  3172.             if (element_type == this_control.boolean_type) i = 4;    // T_BOOLEAN
  3173.             else if (element_type == this_control.char_type)  i = 5; // T_CHAR
  3174.             else if (element_type == this_control.float_type) i = 6; // T_FLOAT
  3175.             else if (element_type == this_control.double_type) i = 7;// T_DOUBLE
  3176.             else if (element_type == this_control.byte_type) i = 8;  // T_BYTE
  3177.             else if (element_type == this_control.short_type)  i = 9;// T_SHORT
  3178.             else if (element_type == this_control.int_type) i = 10;  // T_INT
  3179.             else if (element_type == this_control.long_type) i = 11; // T_LONG
  3180.             else            chaos("new array unsupported type");
  3181.             PutOp(OP_NEWARRAY);
  3182.             PutU1(i);
  3183.             return;
  3184.         }
  3185.         else {
  3186.             // must be reference type
  3187.             PutOp(OP_ANEWARRAY);
  3188.             PutU2(RegisterClass(element_type -> fully_qualified_name));
  3189.         }
  3190.     }
  3191.     else {
  3192.         PutOp(OP_MULTIANEWARRAY);
  3193.         PutU2(RegisterClass(type -> signature));
  3194.         PutU1(dims);  // load dims count
  3195.         ChangeStack(dims-1);  // dims -1
  3196.     }
  3197. }
  3198.  
  3199. int ByteCode::EmitPostUnaryExpression(AstPostUnaryExpression *expression,int need_value) 
  3200. {
  3201.             // POST_UNARY
  3202.     int kind;
  3203.         switch(kind=GetLHSKind(expression -> expression, expression -> write_method)) {
  3204.         case LHS_LOCAL:
  3205.         case LHS_STATIC:
  3206.         case LHS_STATIC_METHOD:
  3207.             EmitPostUnaryExpressionSimple(kind,expression,need_value);
  3208.             break;
  3209.         case LHS_ARRAY:
  3210.             EmitPostUnaryExpressionArray(expression, need_value);
  3211.             break;
  3212.         case LHS_FIELD:
  3213.         case LHS_CLASS_METHOD:
  3214.             EmitPostUnaryExpressionField(kind,expression,need_value);
  3215.             break;
  3216.         default:
  3217.             chaos("unknown lhs kind for assignment");
  3218.     }
  3219.     return GetTypeWords(expression-> Type());
  3220. }
  3221.  
  3222. void ByteCode::EmitPostUnaryExpressionField(int kind,AstPostUnaryExpression *expression,int need_value) 
  3223. {
  3224. //    AstExpression *expression;
  3225.     // POST_UNARY on instance variable
  3226.     // load value of field, duplicate, do increment or decrement, then store back, leaving original value
  3227.     // on top of stack.
  3228.     VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
  3229.     TypeSymbol * type = (TypeSymbol *) sym -> owner;
  3230.     TypeSymbol * expression_type = expression-> Type();
  3231.     bool plus = (expression -> post_unary_tag  ==  AstPostUnaryExpression::PLUSPLUS) ? true : false;
  3232.  
  3233.     if (kind==LHS_FIELD) {
  3234.         EmitFieldAccessLHS(expression -> expression);
  3235.     }
  3236.     else {
  3237.         ResolveAccess(expression -> expression, 1); // get address and value
  3238.     }
  3239.  
  3240.     if (need_value) {
  3241.         if (this_control.IsDoubleWordType(expression_type)) {
  3242.         PutOp(OP_DUP2_X1);
  3243.         }
  3244.         else PutOp(OP_DUP_X1);
  3245.     }
  3246.     if (this_control.IsSimpleIntegerValueType(expression_type)) {   // TBSL: use iinc eventually
  3247.             PutOp(OP_ICONST_1);
  3248.             PutOp(plus ? OP_IADD : OP_ISUB);
  3249.     }
  3250.     else if (expression_type == this_control.long_type) {
  3251.         PutOp(OP_LCONST_1);
  3252.         PutOp(plus ? OP_LADD : OP_LSUB);
  3253.     }
  3254.     else if (expression_type == this_control.float_type) {
  3255.         PutOp(OP_FCONST_1);
  3256.         PutOp(plus ? OP_FADD : OP_FSUB);
  3257.     }
  3258.     else if (expression_type == this_control.double_type) {
  3259.         PutOp(OP_DCONST_1);                // load 1.0
  3260.         PutOp(plus ? OP_DADD : OP_DSUB);
  3261.     }
  3262.     if (kind==LHS_FIELD) {
  3263.         PutOp(OP_PUTFIELD);
  3264.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
  3265.         PutU2(GenerateFieldReference(sym));
  3266.     }
  3267.     else {
  3268.         int stack_words = this_control.IsDoubleWordType(expression_type) ? 2: 1;
  3269.         PutOp(OP_INVOKEVIRTUAL);
  3270.         CompleteCall(expression -> write_method, stack_words, 0);
  3271.     }
  3272. }
  3273.  
  3274. void ByteCode::EmitPostUnaryExpressionSimple(int kind, AstPostUnaryExpression *expression, int need_value) 
  3275. {
  3276. //    AstExpression *expression;
  3277.     // POST_UNARY on local variable
  3278.     // load value of variable, duplicate, do increment or decrement, then store back, leaving original value
  3279.     // on top of stack.
  3280.     bool plus = (expression -> post_unary_tag  ==  AstPostUnaryExpression::PLUSPLUS) ? true : false;
  3281.     TypeSymbol * expression_type = expression-> Type();
  3282.  
  3283.     if (expression_type == this_control.int_type) { // see if can use IINC
  3284.         if (IsLocal(expression)) {
  3285.         if (need_value)  (void) LoadSimple(kind, expression);
  3286.           PutOp(OP_IINC);
  3287.           PutU1(expression -> symbol -> VariableCast() -> LocalVariableIndex());
  3288.           PutI1(plus ? 1 : -1);
  3289.           return;
  3290.         }
  3291.     }
  3292.     LoadSimple(kind,expression -> expression); // this will also load value needing resolution
  3293.  
  3294.     if (need_value) {
  3295.         if (this_control.IsDoubleWordType(expression_type)) {
  3296.         PutOp(OP_DUP2);
  3297.         }
  3298.         else PutOp(OP_DUP);
  3299.     }
  3300.     if (this_control.IsSimpleIntegerValueType(expression_type)) {               // TBSL: use iinc eventually
  3301.             PutOp(OP_ICONST_1);
  3302.             PutOp(plus ? OP_IADD : OP_ISUB);
  3303.             EmitCast(expression_type, this_control.int_type);
  3304.     }
  3305.     else if (expression_type == this_control.long_type) {
  3306.         PutOp(OP_LCONST_1);
  3307.         PutOp(plus ? OP_LADD : OP_LSUB);
  3308.     }
  3309.     else if (expression_type == this_control.float_type) {
  3310.         PutOp(OP_FCONST_1);
  3311.         PutOp(plus ? OP_FADD : OP_FSUB);
  3312.     }
  3313.     else if (expression_type == this_control.double_type) {
  3314.         PutOp(OP_DCONST_1);                // load 1.0
  3315.         PutOp(plus ? OP_DADD : OP_DSUB);
  3316.     }
  3317.     if (kind==LHS_STATIC_METHOD) {
  3318.         int stack_words = this_control.IsDoubleWordType(expression_type) ? 2: 1;
  3319.         PutOp(OP_INVOKESTATIC);
  3320.         CompleteCall(expression -> write_method, stack_words, 0);
  3321.     }
  3322.     else {
  3323.         StoreSimple(kind,expression -> expression);
  3324.     }
  3325. }
  3326.  
  3327.  
  3328. void ByteCode::EmitPostUnaryExpressionArrayCode(int load_op,
  3329.                                                 int need_value,
  3330.                                                 int dup_op,
  3331.                                                 int const_op,
  3332.                                                 int plus,
  3333.                                                 int add_op,
  3334.                                                 int sub_op,
  3335.                                                 int store_op,
  3336.                                                 int conv_op) 
  3337. {
  3338.     PutOp(load_op);
  3339.     if (need_value)PutOp(dup_op);  // save value below saved array base and index
  3340.     PutOp(const_op);
  3341.     PutOp(plus ? add_op : sub_op);
  3342.     if (conv_op) PutOp(conv_op); // if need to convert back to desired type
  3343.     PutOp(store_op);
  3344. }
  3345.  
  3346. void ByteCode::EmitPostUnaryExpressionArray(AstPostUnaryExpression *expression, int need_value) 
  3347. {
  3348.     // Post Unary for which operand is array element
  3349.     // assignment for which lhs is array element
  3350. //    AstExpression *expression;
  3351.     bool plus = (expression -> post_unary_tag  ==  AstPostUnaryExpression::PLUSPLUS) ? true : false;
  3352.     TypeSymbol * expression_type = expression-> Type();
  3353.     EmitArrayAccessLHS((AstArrayAccess *)expression -> expression); // lhs must be array access
  3354.     PutOp(OP_DUP2); // save array base and index for later store
  3355.     if (expression_type == this_control.int_type) {
  3356.         EmitPostUnaryExpressionArrayCode(OP_IALOAD, need_value, OP_DUP_X2,
  3357.         OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_IASTORE, 0);
  3358.     }
  3359.     else if (expression_type == this_control.byte_type ) {
  3360.         EmitPostUnaryExpressionArrayCode(OP_BALOAD, need_value, OP_DUP_X2,
  3361.         OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_BASTORE, OP_I2B);
  3362.     }
  3363.     else if (expression_type == this_control.char_type ) {
  3364.         EmitPostUnaryExpressionArrayCode(OP_CALOAD, need_value, OP_DUP_X2,
  3365.         OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_CASTORE, OP_I2C);
  3366.     }
  3367.     else if (expression_type == this_control.short_type) {
  3368.         EmitPostUnaryExpressionArrayCode(OP_SALOAD, need_value, OP_DUP_X2,
  3369.         OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_SASTORE, OP_I2S);
  3370.     }
  3371.     else if (expression_type == this_control.long_type) {
  3372.         EmitPostUnaryExpressionArrayCode(OP_LALOAD, need_value, OP_DUP2_X2,
  3373.         OP_LCONST_1, plus, OP_LADD, OP_LSUB, OP_LASTORE, 0);
  3374.     }
  3375.     else if (expression_type == this_control.float_type) {
  3376.         EmitPostUnaryExpressionArrayCode(OP_FALOAD, need_value, OP_DUP_X2,
  3377.         OP_FCONST_1, plus, OP_FADD, OP_FSUB, OP_FASTORE, 0);
  3378.     }
  3379.     else if (expression_type == this_control.double_type) {
  3380.         EmitPostUnaryExpressionArrayCode(OP_DALOAD, need_value, OP_DUP2_X2,
  3381.         OP_DCONST_1, plus, OP_DADD, OP_DSUB, OP_DASTORE, 0);
  3382.     }
  3383.     else    chaos("unsupported postunary type");
  3384. }
  3385.  
  3386. int ByteCode::EmitPreUnaryExpression(AstPreUnaryExpression *expression,int need_value) 
  3387. {
  3388.             // PRE_UNARY
  3389.     TypeSymbol * type = expression-> Type();
  3390.     if (expression -> pre_unary_tag  ==  AstPreUnaryExpression::PLUSPLUS ||
  3391.         expression -> pre_unary_tag  ==  AstPreUnaryExpression::MINUSMINUS) {
  3392.         EmitPreUnaryIncrementExpression(expression,need_value);
  3393.     }
  3394.     else {
  3395.     // here for ordinary unary operator without side effects.
  3396.     switch (expression -> pre_unary_tag) {
  3397.         case AstPreUnaryExpression::PLUS:
  3398.             // nothing to do (front-end will have done any needed conversions)
  3399.             EmitExpression(expression -> expression);
  3400.             break;
  3401.         case AstPreUnaryExpression::MINUS:
  3402.             EmitExpression(expression -> expression);
  3403.             if (this_control.IsSimpleIntegerValueType(type)) PutOp(OP_INEG);
  3404.             else if (type == this_control.long_type) PutOp(OP_LNEG);
  3405.             else if (type == this_control.float_type)    PutOp(OP_FNEG);
  3406.             else if (type == this_control.double_type)   PutOp(OP_DNEG);
  3407.             else chaos("unary minus on unsupported type");
  3408.             break;
  3409.         case AstPreUnaryExpression::TWIDDLE:
  3410.             if (this_control.IsSimpleIntegerValueType(type)) {
  3411.             EmitExpression(expression -> expression);
  3412.             PutOp(OP_ICONST_M1);           // -1
  3413.             PutOp(OP_IXOR);                // exclusive or to get result
  3414.             }
  3415.             else if (type == this_control.long_type) {
  3416.             EmitExpression(expression -> expression);
  3417.             PutOp(OP_LCONST_1);            // make -1
  3418.             PutOp(OP_LNEG);
  3419.             PutOp(OP_LXOR);                // exclusive or to get result
  3420.             }
  3421.             else chaos("unary ~ on unsupported type");
  3422.             break;
  3423.         case AstPreUnaryExpression::NOT: 
  3424.             if (type == this_control.boolean_type) {
  3425.                 Label lab1,lab2;
  3426.                 EmitExpression(expression -> expression);
  3427.                 EmitBranch(OP_IFEQ,lab1);
  3428.                 PutOp(OP_ICONST_0);        // turn true into false
  3429.                 EmitBranch(OP_GOTO,lab2);
  3430.                 DefineLabel(lab1);
  3431.                 PutOp(OP_ICONST_1);        // here to turn false into true
  3432.                 DefineLabel(lab2);
  3433.                 CompleteLabel(lab1);
  3434.                 CompleteLabel(lab2);
  3435.             }
  3436.             else chaos("unary ! on non-boolean not supported");
  3437.             break;
  3438.         default:
  3439.             chaos("unknown preunary tag");
  3440.     }
  3441.     }
  3442.     return GetTypeWords(type);
  3443. //    AstExpression *expression;
  3444. }
  3445.     
  3446. void ByteCode::EmitPreUnaryIncrementExpression(AstPreUnaryExpression *expression, int need_value) 
  3447. {
  3448.             // PRE_UNARY with side effects (++X or --X)
  3449.     int kind;
  3450.         switch(kind=GetLHSKind(expression, expression -> write_method)) {
  3451.         case LHS_LOCAL:
  3452.         case LHS_STATIC:
  3453.         case LHS_STATIC_METHOD:
  3454.             EmitPreUnaryIncrementExpressionSimple(kind,expression,need_value);
  3455.             break;
  3456.         case LHS_ARRAY:
  3457.             EmitPreUnaryIncrementExpressionArray(expression,need_value);
  3458.             break;
  3459.         case LHS_FIELD:
  3460.         case LHS_CLASS_METHOD:
  3461.             EmitPreUnaryIncrementExpressionField(kind, expression,need_value);
  3462.         break;
  3463.         default:
  3464.             chaos("unknown lhs kind for assignment");
  3465.     }
  3466. }
  3467.  
  3468. void ByteCode::EmitPreUnaryIncrementExpressionSimple(int kind,AstPreUnaryExpression *expression, int need_value) 
  3469. {
  3470. //    AstExpression *expression;
  3471.     // POST_UNARY on name
  3472.     // load value of variable, do increment or decrement, duplicate, then store back, leaving original value
  3473.     // on top of stack.
  3474.     bool plus = (expression -> pre_unary_tag  ==  AstPreUnaryExpression::PLUSPLUS) ? true : false;
  3475.     TypeSymbol * type = expression-> Type();
  3476.     if (type == this_control.int_type) {
  3477.  
  3478.         if (kind == LHS_LOCAL) {
  3479.           PutOp(OP_IINC);
  3480.           PutU1(expression -> symbol -> VariableCast() -> LocalVariableIndex());
  3481.           PutI1(plus ? 1 : -1);
  3482.           if (need_value) (void) LoadSimple(kind, expression);
  3483.           return;
  3484.         }
  3485.     }
  3486.     (void) LoadSimple(kind,expression -> expression); // will also load value if resolution needed
  3487.  
  3488.     if (this_control.IsSimpleIntegerValueType(type)) {              // TBSL: use iinc eventually
  3489.         PutOp(OP_ICONST_1);
  3490.         PutOp(plus ? OP_IADD : OP_ISUB);
  3491.         EmitCast(type, this_control.int_type);
  3492.         if (need_value) PutOp(OP_DUP);
  3493.     }
  3494.     else if (type == this_control.long_type) {
  3495.         PutOp(OP_LCONST_1);
  3496.         PutOp(plus ? OP_LADD : OP_LSUB);
  3497.         if (need_value) PutOp(OP_DUP2);
  3498.     }
  3499.     else if (type == this_control.float_type) {
  3500.         PutOp(OP_FCONST_1);
  3501.         PutOp(plus ? OP_FADD : OP_FSUB);
  3502.         if (need_value) PutOp(OP_DUP);
  3503.     }
  3504.     else if (type == this_control.double_type) {
  3505.         PutOp(OP_DCONST_1);                // load 1.0
  3506.         PutOp(plus ? OP_DADD : OP_DSUB);
  3507.         if (need_value) PutOp(OP_DUP2);
  3508.     }
  3509.     if (kind==LHS_STATIC_METHOD) {
  3510.         int stack_words = this_control.IsDoubleWordType(type) ? 2: 1;
  3511.         PutOp(OP_INVOKESTATIC);
  3512.         CompleteCall(expression -> write_method, stack_words, 0);
  3513.     }
  3514.     else {
  3515.         StoreSimple(kind,expression);
  3516.     }
  3517. }
  3518.  
  3519. void ByteCode::EmitPreUnaryIncrementExpressionArrayCode(int load_op,
  3520.                                                         int const_op,
  3521.                                                         int plus,
  3522.                                                         int add_op,
  3523.                                                         int sub_op,
  3524.                                                         int need_value,
  3525.                                                         int dup_op,
  3526.                                                         int store_op,
  3527.                                                         int conv_op) 
  3528. {
  3529.     PutOp(load_op);
  3530.     PutOp(const_op);
  3531.     PutOp(plus ? add_op : sub_op);
  3532.     if (need_value) PutOp(dup_op); // save value below saved array base and index
  3533.     if (conv_op) PutOp(conv_op); // if need to check result in range
  3534.     PutOp(store_op);
  3535. }
  3536.  
  3537. void ByteCode::EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression *expression, int need_value) 
  3538. {
  3539.     // Post Unary for which operand is array element
  3540.     // assignment for which lhs is array element
  3541. //    AstExpression *expression;
  3542.     bool plus = (expression -> pre_unary_tag  ==  AstPreUnaryExpression::PLUSPLUS) ? true : false;
  3543.     TypeSymbol * type = expression-> Type();
  3544.     EmitArrayAccessLHS((AstArrayAccess *)expression -> expression); // lhs must be array access
  3545.     PutOp(OP_DUP2); // save array base and index for later store
  3546.     if (type == this_control.int_type) {
  3547.         EmitPreUnaryIncrementExpressionArrayCode(OP_IALOAD, OP_ICONST_1,
  3548.         plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_IASTORE,0);   
  3549.     }
  3550.     else if (type == this_control.byte_type) {
  3551.         EmitPreUnaryIncrementExpressionArrayCode(OP_BALOAD, OP_ICONST_1,
  3552.         plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_BASTORE, OP_I2B); 
  3553.     }
  3554.     else if (type == this_control.char_type) {
  3555.         EmitPreUnaryIncrementExpressionArrayCode(OP_CALOAD, OP_ICONST_1,
  3556.         plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_CASTORE, OP_I2C); 
  3557.     }
  3558.     else if (type == this_control.short_type) {
  3559.         EmitPreUnaryIncrementExpressionArrayCode(OP_SALOAD, OP_ICONST_1,
  3560.         plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_SASTORE, OP_I2S); 
  3561.     }
  3562.     else if (type == this_control.long_type) {
  3563.         EmitPreUnaryIncrementExpressionArrayCode(OP_LALOAD, OP_LCONST_1,
  3564.         plus, OP_LADD, OP_LSUB, need_value, OP_DUP2_X2, OP_LASTORE, 0); 
  3565.     }
  3566.     else if (type == this_control.float_type)    {
  3567.         EmitPreUnaryIncrementExpressionArrayCode(OP_FALOAD, OP_FCONST_1,
  3568.         plus, OP_FADD, OP_FSUB, need_value, OP_DUP_X2, OP_FASTORE, 0);  
  3569.     }
  3570.     else if (type == this_control.double_type) {
  3571.         EmitPreUnaryIncrementExpressionArrayCode(OP_DALOAD, OP_DCONST_1,
  3572.         plus, OP_DADD, OP_DSUB, need_value, OP_DUP2_X2, OP_DASTORE, 0); 
  3573.     }
  3574.     else chaos("unsupported PreUnary type");
  3575. }
  3576.  
  3577. void ByteCode::EmitPreUnaryIncrementExpressionField(int kind, AstPreUnaryExpression *expression, int need_value) 
  3578. {
  3579.     // Pre Unary for which operand is field (instance variable)
  3580. //    AstExpression *expression;
  3581.     bool plus = (expression -> pre_unary_tag  ==  AstPreUnaryExpression::PLUSPLUS) ? true : false;
  3582.     VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
  3583.     TypeSymbol * type = (TypeSymbol *) sym -> owner;
  3584.     TypeSymbol * expression_type = expression-> Type();
  3585.     if (kind==LHS_CLASS_METHOD) {
  3586.         // need to load address of object, obtained from resolution, saving a copy on the stack
  3587.         ResolveAccess(expression -> expression, 1); // get address and value
  3588.     }
  3589.     else {
  3590.         EmitFieldAccessLHS(expression -> expression);
  3591.     }
  3592.         if (this_control.IsSimpleIntegerValueType(expression_type)) {
  3593.         PutOp(OP_ICONST_1);
  3594.         PutOp(plus ? OP_IADD : OP_ISUB);
  3595.         EmitCast(expression_type, this_control.int_type);
  3596.         if (need_value)PutOp(OP_DUP_X1);
  3597.     }
  3598.     else if (expression_type == this_control.long_type) {
  3599.         PutOp(OP_LCONST_1);
  3600.         PutOp(plus ? OP_LADD : OP_LSUB);
  3601.         if (need_value)PutOp(OP_DUP2_X1);
  3602.     }
  3603.     else if (expression_type == this_control.float_type) {
  3604.         PutOp(OP_FCONST_1);
  3605.         PutOp(plus ? OP_FADD : OP_FSUB);
  3606.         if (need_value)PutOp(OP_DUP_X1);
  3607.     }
  3608.     else if (expression_type == this_control.double_type) {
  3609.         PutOp(OP_DCONST_1);
  3610.         PutOp(plus ? OP_DADD : OP_DSUB);
  3611.         if (need_value)PutOp(OP_DUP2_X1);
  3612.     }
  3613.     else    chaos("unsupported PreUnary type");
  3614.     if (kind==LHS_CLASS_METHOD) {
  3615.         int stack_words = this_control.IsDoubleWordType(expression_type) ? 2: 1;
  3616.         PutOp(OP_INVOKEVIRTUAL);
  3617.         CompleteCall(expression -> write_method, stack_words, 0);
  3618.     }
  3619.     else {
  3620.         PutOp(OP_PUTFIELD);
  3621.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
  3622.         PutU2(GenerateFieldReference(sym));
  3623.     }
  3624. }
  3625.  
  3626. void ByteCode::EmitThisInvocation(AstThisCall *this_call)
  3627. {
  3628.     MethodSymbol * msym = this_call -> symbol;
  3629.     AstExpression *base_opt = this_call -> base_opt;
  3630.  
  3631.     // THIS_CALL
  3632.     //    AstExpression *method;
  3633.     //    AstList *arguments;
  3634.     // A call to another constructor (THIS_CALL) or super constructor (SUPER_CALL)
  3635.     // result in the same sort of generated code, as the semantic analysis
  3636.     // has resolved the proper constructor to be invoked.
  3637.     int stack_words = 0; // words on stack needed for arguments
  3638.     PutOp(OP_ALOAD_0); // load 'this'
  3639.     if (base_opt) {
  3640.         stack_words += EmitExpression(base_opt);
  3641.     }
  3642.     for (int i=0; i < this_call -> NumLocalArguments();i++) {
  3643.         stack_words += EmitExpression((AstExpression *) this_call -> LocalArgument(i));
  3644.     }
  3645.     for (int k=0; k < this_call -> NumArguments();k++) {
  3646.         stack_words += EmitExpression((AstExpression *) this_call -> Argument(k));
  3647.     }
  3648.     PutOp(OP_INVOKENONVIRTUAL);
  3649.     ChangeStack(-stack_words);
  3650.     // need to get method index, the constant_pool index for a
  3651.     // reference to this method (a Methodref);
  3652. // caller will supply methodref
  3653.     if (msym -> constant_pool_index == 0 || msym -> constant_pool_class != class_id) { // build method ref for method
  3654.         msym -> constant_pool_index = BuildMethodref(
  3655.             this_class,
  3656.             BuildNameAndType(
  3657.                 RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
  3658.                 RegisterUtf8(msym -> signature)));
  3659.         msym -> constant_pool_class = class_id;
  3660.  
  3661.     }
  3662.     
  3663.     PutU2(msym -> constant_pool_index);
  3664. }
  3665.  
  3666.  
  3667. void ByteCode::EmitSuperInvocation(AstSuperCall *super_call)
  3668. {
  3669.     MethodSymbol *msym = super_call -> symbol;
  3670.     AstExpression *base_opt = super_call -> base_opt;
  3671.  
  3672.     int stack_words = 0; // words on stack needed for arguments
  3673.     PutOp(OP_ALOAD_0); // load 'this'
  3674.     if (base_opt) {
  3675.         stack_words += EmitExpression(base_opt);
  3676.     }
  3677.     for (int i=0; i < super_call -> NumLocalArguments();i++) {
  3678.         stack_words += EmitExpression((AstExpression *) super_call -> LocalArgument(i));
  3679.     }
  3680.     for (int k=0; k < super_call -> NumArguments();k++) {
  3681.         stack_words += EmitExpression((AstExpression *) super_call -> Argument(k));
  3682.     }
  3683.     PutOp(OP_INVOKENONVIRTUAL);
  3684.     ChangeStack(-stack_words);
  3685.     // need to get method index, the constant_pool index for a
  3686.     // reference to this method (a methodref);
  3687.     // caller will supply methodref
  3688.     if (msym -> constant_pool_index == 0 || msym -> constant_pool_class != class_id) { // build method ref for method
  3689.         msym -> constant_pool_index = BuildMethodref(
  3690.             super_class,
  3691.             BuildNameAndType(
  3692.                 RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
  3693.                 RegisterUtf8(msym -> signature)));
  3694.         msym -> constant_pool_class = class_id;
  3695.  
  3696.     }
  3697.     
  3698.     PutU2(msym -> constant_pool_index);
  3699. }
  3700.  
  3701.  
  3702. AstExpression * ByteCode::UnParenthesize(AstExpression * p)
  3703. {
  3704.   // called when expression has been parenthesized to removed
  3705.   // parantheses and expose true structure.
  3706.   AstParenthesizedExpression * pe;
  3707.   while (p -> ParenthesizedExpressionCast()) {
  3708.       p = p -> ParenthesizedExpressionCast()  -> expression;
  3709.   }
  3710.   return p;
  3711. }
  3712.  
  3713. //  Methods for string concatenation
  3714.  
  3715. void ByteCode::ConcatenateString(AstBinaryExpression * expression)
  3716. {
  3717.     // generate code to concatenate strings, by generating a string buffer and appending the arguments
  3718.     // before calling toString, i.e.,
  3719.     //  s1+s2 compiles to
  3720.     //  new StringBuffer().append(s1).append(s2).toString();
  3721.     // look for sequences of concatenation to use a single buffer where possible
  3722.         EmitStringBuffer();
  3723.     AppendString(expression -> left_expression); 
  3724.     AppendString(expression -> right_expression);
  3725.     EmitCallStringToString(); // convert string buffer to string
  3726. }
  3727.  
  3728. void ByteCode::EmitCallStringToString()
  3729. { // generate call to toString on stringbuffer
  3730.     PutOp(OP_INVOKEVIRTUAL);
  3731.     PutU2(RegisterMethod(METHOD_STRINGBUFFER_TOSTRING));
  3732.     ChangeStack(1); // account for return value
  3733. }
  3734. void ByteCode::EmitStringBuffer()
  3735. {
  3736.     // generate code to allocate new string buffer and initialize it
  3737.     PutOp(OP_NEW);
  3738.     PutU2(RegisterClass(U8S_java_SL_lang_SL_StringBuffer, strlen(U8S_java_SL_lang_SL_StringBuffer)));
  3739.     PutOp(OP_DUP);
  3740.     PutOp(OP_INVOKENONVIRTUAL);
  3741.     PutU2(RegisterMethod(METHOD_STRINGBUFFER_INIT));
  3742. }
  3743.  
  3744. void ByteCode::AppendString(AstExpression * p)
  3745. {
  3746.     AstBinaryExpression *binexpr;
  3747.     TypeSymbol * type = p-> Type();
  3748.     if (p -> BinaryExpressionCast()) {
  3749.         binexpr = p -> BinaryExpressionCast();
  3750.        if ( binexpr -> binary_tag == AstBinaryExpression::PLUS
  3751.             && (IsReferenceType(binexpr -> left_expression-> Type()) ||
  3752.         IsReferenceType(binexpr -> right_expression-> Type()))) {
  3753.             AppendString(binexpr -> left_expression);
  3754.             AppendString(binexpr -> right_expression);
  3755.             return;
  3756.         } 
  3757.     }
  3758.     if (p -> ParenthesizedExpressionCast()) {
  3759.         AppendString(p -> ParenthesizedExpressionCast() -> expression);
  3760.         return;
  3761.     }
  3762.     if (p -> CastExpressionCast()) { // here if cast expression, verify that converting to string
  3763.         AstCastExpression *cast = (AstCastExpression *) p;
  3764.         if (cast->kind == Ast::CAST && cast-> Type() == this_control.String()) {
  3765.           AppendString(cast->expression);
  3766.           return;
  3767.         }
  3768.     }
  3769.     if (type == this_control.null_type) {
  3770.         // replace explicit reference to "null" by 
  3771.         // corresponding string.
  3772.         name_StringNull = BuildString(RegisterUtf8(U8S_null, strlen(U8S_null)));
  3773.         if (name_StringNull <=255) {
  3774.             PutOp(OP_LDC);
  3775.             PutU1((unsigned char) name_StringNull);
  3776.         }
  3777.         else {
  3778.             PutOp(OP_LDC_W);
  3779.             PutU2(name_StringNull);
  3780.         }
  3781.         type = this_control.String();
  3782.     }
  3783.     else {
  3784.         EmitExpression(p);
  3785.     }
  3786.     EmitStringAppendMethod(type);
  3787. }
  3788.  
  3789. void ByteCode::EmitStringAppendMethod(TypeSymbol * type) 
  3790. {
  3791.     int method_sig = 0;
  3792.     int stack_words = 1; // assume one word put on stack
  3793.     // call appropriate append routine to add to string buffer
  3794.     if (type -> num_dimensions == 1 && type -> base_type == this_control.char_type) {
  3795.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDCHARARRAY);
  3796.     }
  3797.     else if (type == this_control.char_type) {
  3798.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDCHAR);
  3799.     }
  3800.     else if (type == this_control.boolean_type) {
  3801.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDBOOLEAN);
  3802.     }
  3803.     else if (type == this_control.int_type|| type == this_control.short_type || type == this_control.byte_type) {
  3804.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDINT);
  3805.     }
  3806.     else if (type == this_control.long_type) {
  3807.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDLONG);
  3808.         stack_words++;
  3809.     }
  3810.     else if (type == this_control.float_type) {
  3811.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDFLOAT);
  3812.     }
  3813.     else if (type == this_control.double_type) {
  3814.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDDOUBLE);
  3815.         stack_words++;
  3816.     }
  3817.     else if (type == this_control.String()) {
  3818.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDSTRING);
  3819.     }
  3820.     else if (IsReferenceType(type)) {
  3821.         // may need to call toString method on object before appending to stringbuffer
  3822.         // TODO: do above
  3823.         method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDOBJECT);
  3824.     }
  3825.     else {
  3826.         chaos("unexpected string buffer append operand");
  3827.     }
  3828.     PutOp(OP_INVOKEVIRTUAL);
  3829.     ChangeStack(-stack_words);
  3830.     PutU2(method_sig);
  3831.     ChangeStack(1); // account for return value
  3832.     if (method_sig == 0) chaos("unable to find type for string buffer concatenation");
  3833. }
  3834. void ByteCode::chaos(char *msg) {
  3835.  cout << "chaos: " << msg << "\n";
  3836.  cerr << "chaos: " << msg << "\n";
  3837.  exit(1);
  3838. }
  3839. #ifdef TEST
  3840. static void op_trap()
  3841. {
  3842.     int i=0;
  3843.     // used for debugger trap
  3844. }
  3845. #endif
  3846.  
  3847. ByteCode::ByteCode(TypeSymbol *unit_type) : ClassFile(unit_type),
  3848.                                             this_semantic(*unit_type -> semantic_environment -> sem),
  3849.                                             this_control(unit_type -> semantic_environment -> sem -> control)
  3850. {
  3851.     int i;
  3852.  
  3853. #ifdef TEST
  3854.     if (this_control.option.nowrite == 0) {
  3855.         this_control.class_files_written++;
  3856.     }
  3857. #endif
  3858.     this_control.class_file_id++;
  3859.     class_id = this_control.class_file_id;
  3860.     initialize_statics_in_clinit = 1;
  3861.     stack_depth = 0;
  3862.     synchronized_blocks = 0;
  3863.     finally_blocks = 0;
  3864.     
  3865.     for (i=0;i<METHOD_NUMBER;i++) registered_methods[i] = 0;
  3866.     name_StringNull=0;
  3867.  
  3868.     access_flags = unit_type -> access_flags;
  3869.     // The flags for 'static' and 'protected' are set only for the inner
  3870.     // classes attribute, not for the class, as described in page 25
  3871.     // of the inner classes document.
  3872.     if (unit_type -> ACC_PROTECTED()) {
  3873.         access_flags |= 0x0001; // set PUBLIC if PROTECTED
  3874.     }
  3875.     access_flags &= (~ 0x0008); // ResetACC_STATIC
  3876.     access_flags &= (~ 0x0004); // ResetACC_PROTECTED
  3877.     access_flags &= (~ 0x0002); // ResetACC_PRIVATE
  3878.  
  3879.     access_flags |= 0x0020; // must be set always set ACC_SUPER for class (cf page 86 of JVM Spec)
  3880.     
  3881.     magic = 0xcafebabe;
  3882.     major_version = 45;             // use Sun JDK 1.0 version numbers
  3883.     minor_version = 3;
  3884.     constant_pool.Next()=NULL;
  3885.     this_class = RegisterClass(unit_type -> fully_qualified_name);
  3886.  
  3887.     if (unit_type -> super) {
  3888.         super_class = RegisterClass(unit_type -> super -> fully_qualified_name);
  3889.     }
  3890.     else {
  3891.         super_class=0; // primordial beast Object
  3892.     }
  3893.  
  3894.     for (i=0; i<unit_type -> NumInterfaces();i++) {
  3895.         interfaces.Next() = RegisterClass(unit_type -> Interface(i) -> fully_qualified_name);
  3896.     }
  3897.  
  3898.     return;
  3899. }
  3900.  
  3901.  
  3902. //  Methods for manipulating labels
  3903.  
  3904. void ByteCode::DefineLabel(Label& lab)
  3905. {
  3906.     if (lab.defined){
  3907.         chaos( "duplicate label definition");
  3908.     }
  3909.     lab.defined = 1;
  3910.     lab.definition = code_attribute -> code.Length();
  3911.     if (lab.definition > last_label_pc) {
  3912.         last_label_pc = lab.definition;
  3913.     }
  3914. }
  3915. void ByteCode::CompleteLabel(Label& lab)
  3916. {
  3917.     // patch all uses to have proper value. This requires that
  3918.     // all labels be freed at some time.
  3919.     if (lab.uses.Length()) {
  3920.         if (lab.defined == 0) {
  3921.             chaos("label used but with no definition");
  3922.         }                 
  3923.         for (int i=0; i<lab.uses.Length();i++) {
  3924.             // patch byte code reference to label to reflect it's definition
  3925.             // as 16-bit signed offset.
  3926.             unsigned int luse = lab.uses[i].use_offset;;
  3927.             int start =  luse - lab.uses[i].op_offset;
  3928.             int offset = lab.definition - start;
  3929.             if (lab.uses[i].use_length == 2) {
  3930.                 // here if short offset
  3931.                 code_attribute -> code[luse] = (offset >> 8) & 0xFF;
  3932.                 code_attribute -> code[luse+1] = offset & 0xFF;
  3933.             }
  3934.             else if (lab.uses[i].use_length == 4) {
  3935.                 //here if 4 byte use
  3936.                 code_attribute -> code[luse] = (offset >> 24) & 0xFF;
  3937.                 code_attribute -> code[luse+1] = (offset >> 16) & 0xFF;
  3938.                 code_attribute -> code[luse+2] = (offset >> 8) & 0xFF;
  3939.                 code_attribute -> code[luse+3] = offset & 0xFF;
  3940.             }
  3941.             else {
  3942.                 chaos(  "label use length not 2 or 4");
  3943.                 exit(1);
  3944.             }
  3945.  
  3946.         }
  3947.         lab.uses.Reset();
  3948.     }
  3949.     // reset in case label is used again.
  3950.     lab.definition = 0;
  3951.     lab.defined=0;
  3952. }
  3953.  
  3954.  
  3955. int ByteCode::IsLabelUsed(Label& lab)
  3956. {
  3957.     return (lab.uses.Length()>0);
  3958. }
  3959.  
  3960. // int ByteCode::IsLabelDefined(Label& lab)
  3961. // {
  3962. //     return (lab.defined != 0);
  3963. // }
  3964.  
  3965. void ByteCode::UseLabel(Label & lab,int _length, int _op_offset)
  3966. {
  3967.     int lab_index = lab.uses.NextIndex();
  3968.     lab.uses[lab_index].use_length = _length;
  3969.     lab.uses[lab_index].op_offset = _op_offset;
  3970.     lab.uses[lab_index].use_offset = code_attribute -> code.Length();
  3971.  
  3972.     // fill next length bytes with zero; will be filled in with proper value when label completed
  3973.     for (int i=0;i<lab.uses[lab_index].use_length;i++) code_attribute -> code.Next() = 0;
  3974. }
  3975.  
  3976. //  Methods to query attributes
  3977.  
  3978. int ByteCode::IsLocal(AstExpression *p)
  3979. {
  3980.     // return 1 if p refers to local variable, 0 otherwise
  3981.     VariableSymbol *sym = p -> symbol -> VariableCast();
  3982.     return (sym && sym -> owner -> MethodCast()) ? 1 : 0;
  3983. }
  3984.  
  3985. int ByteCode::IsNull(AstExpression *p)
  3986. {
  3987.     // see if operand is null. The front-end will have inserted a cast
  3988.     // of null to the present type
  3989.     if (p -> CastExpressionCast()) {
  3990.         return p -> CastExpressionCast() -> expression-> Type() == this_control.null_type;
  3991.     }
  3992.     else return 0;
  3993. }   
  3994.  
  3995. int ByteCode::IsReferenceType(TypeSymbol *p)
  3996. {
  3997.     return (! (this_control.IsNumeric(p) 
  3998.                || p == this_control.boolean_type || p == this_control.null_type));
  3999. }
  4000.  
  4001.  
  4002. int ByteCode::IsDefaultValue(AstExpression *p)
  4003. {
  4004.     // see if operand is default value of its type
  4005.     TypeSymbol *type = p-> Type();
  4006.     if (!p -> IsConstant()) return 0;
  4007.     LiteralValue * litp = p -> value;
  4008.     if (this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type) {
  4009.         IntLiteralValue * vp = (IntLiteralValue *) litp;
  4010.         int val = vp -> value;
  4011.         return (val == 0);
  4012.     }
  4013.     else if (type == this_control.long_type) {
  4014.         LongLiteralValue * vp = (LongLiteralValue *) litp;
  4015.         LongInt val = vp -> value;
  4016.         return (val == 0);
  4017.     }
  4018.     else if (type == this_control.float_type) {
  4019.         FloatLiteralValue * vp = (FloatLiteralValue *) litp;
  4020.         IEEEfloat val = vp -> value;
  4021.         return (val.Word() == 0);
  4022.     }
  4023.  
  4024.     else if (type == this_control.double_type) {
  4025.         DoubleLiteralValue * vp = (DoubleLiteralValue *) litp;
  4026.         IEEEdouble val = vp -> value;
  4027.         return (val.HighWord() == 0 && val.LowWord() == 0);
  4028.     }
  4029.     else {
  4030.         // the default value for everything else is 'null'
  4031.         return (type == this_control.null_type);
  4032.     }
  4033.  
  4034.     return 0;
  4035. }
  4036.  
  4037. int ByteCode::IsZero(AstExpression *p)
  4038. {
  4039.     // see if operand is integer type and is zero
  4040.     TypeSymbol *type = p-> Type();
  4041.     if (!p -> IsConstant()) return 0;
  4042.     if (p-> Type() == this_control.int_type||p-> Type() == this_control.boolean_type) {
  4043.         LiteralValue * litp = p -> value;
  4044.         IntLiteralValue * vp = (IntLiteralValue *) litp;
  4045.         int val = vp -> value;
  4046.         return (val == 0);
  4047.     }
  4048.     return 0;
  4049. }
  4050. int ByteCode::GetTypeWords(TypeSymbol * type)
  4051. {
  4052.     return this_control.IsDoubleWordType(type) ? 2: 1;
  4053. }
  4054.  
  4055. int ByteCode::GetLHSKind(AstExpression * expression, MethodSymbol * msym)
  4056. {
  4057.     if (msym) { // if has write_method
  4058.         if (msym -> ACC_STATIC())
  4059.             return LHS_STATIC_METHOD;
  4060.         else
  4061.             return LHS_CLASS_METHOD;
  4062.     }
  4063.             
  4064.     if (expression -> CastExpressionCast()) {
  4065.         expression = expression -> CastExpressionCast() -> expression;
  4066.     }
  4067.     else if (expression -> PreUnaryExpressionCast()) {
  4068.         expression = expression -> PreUnaryExpressionCast() -> expression;
  4069.     }
  4070.     else if (expression -> PostUnaryExpressionCast()) {
  4071.         expression = expression -> PostUnaryExpressionCast() -> expression;
  4072.     }
  4073.  
  4074.         //
  4075.         // A left-hand side is either an array access,
  4076.         // a field access or a name. In the case of a FieldAccess
  4077.         // or name, the left-hand side is resolved into a variable.
  4078.         // In the case of an array access, it is resolved into a type.
  4079.         // 
  4080.     VariableSymbol * sym = expression -> symbol -> VariableCast();
  4081.     if (! sym) return LHS_ARRAY;
  4082.     else if (sym -> owner -> MethodCast()) return LHS_LOCAL;
  4083.     else if (sym -> ACC_STATIC()) return LHS_STATIC;
  4084.     else return LHS_FIELD;
  4085. }
  4086.  
  4087. //  Methods to load values
  4088. int ByteCode::GetConstant(LiteralValue *litp, TypeSymbol *type)
  4089. {
  4090.     int lit_index;
  4091.  
  4092.     if (type == this_control.String()) {
  4093.         Utf8LiteralValue *vp = (Utf8LiteralValue *) litp;
  4094.         if (vp -> constant_pool_index_String != 0 && vp -> constant_pool_class == class_id)
  4095.             lit_index = vp -> constant_pool_index_String;
  4096.         else {
  4097.             // must be string
  4098.             lit_index = RegisterString(vp);
  4099.         }
  4100.     }
  4101.     else {
  4102.         if (litp -> constant_pool_index != 0 && litp -> constant_pool_class == class_id)
  4103.             lit_index = litp -> constant_pool_index;
  4104.         else {
  4105.             // load literal using literal value
  4106.             if (this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type) {
  4107.                 IntLiteralValue * vp = (IntLiteralValue *) litp;
  4108.                 lit_index = RegisterInteger(vp);
  4109.             }
  4110.             else if (type == this_control.float_type) {
  4111.                 FloatLiteralValue * vp = (FloatLiteralValue *) litp;
  4112.                 IEEEfloat val = vp -> value;
  4113.                 lit_index = RegisterFloat(vp);
  4114.             }
  4115.             else if (type == this_control.long_type) {
  4116.                 LongLiteralValue * vp = (LongLiteralValue *) litp;
  4117.                 lit_index = RegisterLong(vp);
  4118.             }
  4119.             else if (type == this_control.double_type) {
  4120.                 DoubleLiteralValue * vp = (DoubleLiteralValue *) litp;
  4121.                 lit_index = RegisterDouble(vp);
  4122.             }
  4123.             else chaos("unexpected GetConstant kind");
  4124.         }
  4125.     }
  4126.  
  4127.     return lit_index;
  4128. }
  4129.  
  4130. int ByteCode::LoadConstant(AstExpression *p)
  4131. {
  4132.     // here to load a constant when the LiteralValue is set.
  4133.  
  4134.     LiteralValue * litp = p -> value;
  4135.     if (!p -> IsConstant()) {
  4136.         chaos("constant expected by LoadConstant");
  4137.     }
  4138.     return LoadLiteral(p -> value,p-> Type());
  4139. }
  4140.  
  4141.  
  4142. int ByteCode::LoadLiteral(LiteralValue* litp, TypeSymbol *type) 
  4143. {
  4144.     //    int lit_index = litp -> constant_pool_index;
  4145.     int lit_index;
  4146.     int is_long_or_double=0; // set if need lcd2_w
  4147.     if (litp -> constant_pool_index >0 && litp -> constant_pool_class == class_id) lit_index= litp -> constant_pool_index;
  4148.     else lit_index = 0;
  4149.     // see if can load without using LDC even if have literal index; otherwise generate constant pool entry
  4150.     // if one has not yet been generated.
  4151.     if (litp == this_control.NullValue()) {
  4152.         PutOp(OP_ACONST_NULL);
  4153.         return 1;
  4154.     }
  4155.     if (type == this_control.String()) {
  4156.         // register index as string if this has not yet been done
  4157.         Utf8LiteralValue * lv = (Utf8LiteralValue *) litp;
  4158.         lit_index = RegisterString(lv);
  4159.     }
  4160.     // load literal using literal value
  4161.     // note that boolean literal values stored as int literals
  4162.     else if (this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type) {
  4163.         IntLiteralValue * vp = (IntLiteralValue *) litp;
  4164.         int val = vp -> value;
  4165.         if (val >= -32768 && val <32768) {
  4166.             LoadShort(val);
  4167.             return 1;
  4168.         }
  4169.         lit_index = RegisterInteger(vp);
  4170.     }
  4171.     else if (type == this_control.float_type) {
  4172.         FloatLiteralValue * vp = (FloatLiteralValue *) litp;
  4173.         IEEEfloat val = vp -> value;
  4174.         if (val.Word() == 0) { // if float 0.0
  4175.             PutOp(OP_FCONST_0);
  4176.             return 1;
  4177.         }
  4178.         else if (val.Word() == 0x3f800000) { // if float 1.0
  4179.             PutOp(OP_FCONST_1);
  4180.             return 1;
  4181.         }
  4182.         else if (val.Word() == 0x40000000) { // if float 2.0
  4183.             PutOp(OP_FCONST_2);
  4184.             return 1;
  4185.         }
  4186.         lit_index = RegisterFloat(vp);
  4187.     }
  4188.     else if (type == this_control.long_type) {
  4189.         LongLiteralValue * vp = (LongLiteralValue *) litp;
  4190.         LongInt val = vp -> value;
  4191.         if (val == 0) {
  4192.             PutOp(OP_LCONST_0);        // long 0
  4193.             return 2;
  4194.         }
  4195.         else if (val == 1) {
  4196.             PutOp(OP_LCONST_1);        // long 1
  4197.             return 2;
  4198.         }
  4199.         lit_index = RegisterLong(vp);
  4200.         is_long_or_double=1;
  4201.     }
  4202.     else if (type == this_control.double_type) {
  4203.     //
  4204.         DoubleLiteralValue * vp = (DoubleLiteralValue *) litp;
  4205.         IEEEdouble val = vp -> value;
  4206.         if(val.HighWord() == 0 && val.LowWord() == 0) {
  4207.             PutOp(OP_DCONST_0);
  4208.             return 2;
  4209.         }
  4210.         else if (val.HighWord() == 0x3ff00000 && val.LowWord() == 0x00000000) { // if double 1.0
  4211.             PutOp(OP_DCONST_1);
  4212.             return 2;
  4213.         }
  4214.         else { // if need ldc2_w
  4215.             lit_index = RegisterDouble(vp);
  4216.             is_long_or_double=1;
  4217.         }
  4218.     }
  4219.     else {
  4220.         chaos("unsupported constant kind");
  4221.     }
  4222.     if (lit_index == 0) chaos("lit_index zero");
  4223.     if(!is_long_or_double && lit_index <=255) {
  4224.         PutOp(OP_LDC);
  4225.         PutU1(lit_index);
  4226.     }
  4227.     else {
  4228.         PutOp(is_long_or_double ? OP_LDC2_W : OP_LDC_W);
  4229.         PutU2(lit_index);
  4230.     }
  4231.     return is_long_or_double + 1;
  4232. }
  4233. void ByteCode::LoadLocalVariable(VariableSymbol * var)
  4234. {
  4235.     LoadLocal(var -> LocalVariableIndex(), var-> Type());
  4236. }
  4237. void ByteCode::LoadLocal(int varno, TypeSymbol * type)
  4238. {
  4239.     int opc0, opc;
  4240.     if (this_control.IsSimpleIntegerValueType(type)|| type == this_control.boolean_type) {
  4241.         opc0 = OP_ILOAD_0; opc = OP_ILOAD;
  4242.     }
  4243.     else if (type == this_control.long_type) {
  4244.         opc0 = OP_LLOAD_0; opc = OP_LLOAD;
  4245.     }
  4246.     else if (type == this_control.float_type) {
  4247.         opc0 = OP_FLOAD_0; opc = OP_FLOAD;
  4248.     }
  4249.     else if (type == this_control.double_type) {
  4250.         opc0 = OP_DLOAD_0; opc = OP_DLOAD;
  4251.     }
  4252.     else { // assume reference
  4253.         opc0 = OP_ALOAD_0; opc = OP_ALOAD;
  4254.     }
  4255.     if (varno<=3) PutOp(opc0+varno);
  4256.     else if (varno<256) {
  4257.         PutOp(opc); PutU1(varno);
  4258.     }
  4259.     else {
  4260.         PutOp(OP_WIDE); PutOp(opc); PutU2(varno);
  4261.     }
  4262. }
  4263. void ByteCode::LoadInteger(int val)
  4264. {
  4265.     
  4266.     if (val >= -32768 && val <32768) { // if short
  4267.         LoadShort(val);
  4268.     }
  4269.     else {
  4270.         u2 index = BuildInteger(val);
  4271.         if (index <=255) {
  4272.             PutOp(OP_LDC);
  4273.             PutU1((unsigned char) index);
  4274.         }
  4275.         else {
  4276.             PutOp(OP_LDC_W);
  4277.             PutU2(index);
  4278.         }
  4279.     }
  4280. }
  4281.  
  4282. void ByteCode::LoadShort(int val)
  4283. { // load short (signed) value onto stack
  4284.     if (val >= -128 && val <128) {
  4285.         switch (val) {
  4286.             case -1:
  4287.             case 0:
  4288.             case 1:
  4289.             case 2:
  4290.             case 3:
  4291.             case 4:
  4292.             case 5:
  4293.                 PutOp(OP_ICONST_0 + val); // exploit opcode encoding
  4294.                 break;
  4295.             default:        // else put byte value
  4296.                 PutOp(OP_BIPUSH);
  4297.                 PutU1(val);
  4298.         }
  4299.     }
  4300.     else if (val >= -32768 && val <32768) { // if short
  4301.         PutOp(OP_SIPUSH);
  4302.         PutU1((val >> 8)); 
  4303.         PutU1(val);
  4304.     }
  4305.     else {
  4306.         chaos("bcShort operand not short!");
  4307.     }
  4308. }
  4309. void ByteCode::ResolveAccess(AstExpression *p, int need_value)
  4310. {
  4311.     // if need_value zero, then just get address for access of private member
  4312.     // else get value with an extra copy of the needed address below the value
  4313.     AstExpression * resolve;
  4314.     if (p -> FieldAccessCast()) {
  4315.         resolve = p -> FieldAccessCast() -> resolution_opt;
  4316.     }
  4317.     else if (p -> SimpleNameCast()) {
  4318.         resolve = p -> SimpleNameCast() -> resolution_opt;
  4319.     }
  4320.     if (resolve -> MethodInvocationCast()) {
  4321.         if (need_value) {
  4322.             EmitMethodInvocation(resolve -> MethodInvocationCast(), 1);
  4323.         }
  4324.         else {
  4325.     // next does too much, getting base and field value; just want base
  4326.             //Expression(resolve -> MethodInvocationCast() -> method);
  4327.         if (resolve -> MethodInvocationCast() -> method -> FieldAccessCast()) {
  4328.             AstFieldAccess * field_expression = 
  4329.              resolve -> MethodInvocationCast() -> method -> FieldAccessCast();
  4330.     //   VariableSymbol * sym = (VariableSymbol *) field_expression -> owner;
  4331.          EmitExpression (field_expression -> base);
  4332.         }
  4333.         else {
  4334.           chaos("field access expected in method resolution");
  4335.         }
  4336.         }
  4337.     }
  4338.     else {
  4339.         chaos("method invocation expected here");
  4340.     }
  4341. }
  4342.     
  4343. int ByteCode::LoadSimple (int kind,AstExpression *p)
  4344. {
  4345.     VariableSymbol * sym = (VariableSymbol *) p -> symbol;
  4346.     TypeSymbol * type = (TypeSymbol *) sym -> owner;
  4347.     TypeSymbol * expression_type = p-> Type();
  4348.     switch (kind) {
  4349.         case LHS_LOCAL:
  4350.             LoadLocal(sym -> LocalVariableIndex(), expression_type);
  4351.             break;
  4352.         case LHS_STATIC_METHOD:
  4353.             EmitExpression(p); // will do resolution
  4354.             break;
  4355.         case LHS_FIELD:
  4356.         case LHS_STATIC:
  4357.         {
  4358.             if (sym -> ACC_STATIC()) {
  4359.                 PutOp(OP_GETSTATIC);
  4360.                 ChangeStack(GetTypeWords(expression_type));
  4361.             }
  4362.             else {
  4363.                 PutOp(OP_ALOAD_0); // get address of "this"
  4364.                 PutOp(OP_GETFIELD);
  4365.                 ChangeStack(GetTypeWords(expression_type)-1);
  4366.             }
  4367.             PutU2(GenerateFieldReference(sym));
  4368.             break;
  4369.         }
  4370.         default: chaos("LoadSimple bad kind");
  4371.     }
  4372.     return GetTypeWords(expression_type);
  4373. }
  4374.  
  4375. void ByteCode::LoadReference(AstExpression *expression) 
  4376. {
  4377.     //load reference from local variable.
  4378.     // otherwise will use getstatic or getfield.
  4379.     TypeSymbol * type;
  4380.     int is_local=0,varno;
  4381.     if (expression -> ParenthesizedExpressionCast()) {
  4382.         expression = UnParenthesize(expression);
  4383.     }
  4384.     VariableSymbol * sym = expression -> symbol -> VariableCast();
  4385.     if (sym && sym -> owner -> MethodCast()) {
  4386.         is_local=1;
  4387.         varno = sym -> LocalVariableIndex();
  4388.         LoadLocal(varno,expression-> Type());
  4389.         return;
  4390.     }
  4391.     if (expression -> ArrayAccessCast()) { // nested array reference
  4392.         EmitArrayAccessLHS(expression -> ArrayAccessCast());
  4393.         PutOp(OP_AALOAD);
  4394.     }
  4395.     else if (expression -> FieldAccessCast() && expression -> FieldAccessCast() -> resolution_opt) {
  4396.         EmitExpression(expression -> FieldAccessCast() -> resolution_opt);
  4397.         return;
  4398.     }
  4399.     else if (expression -> FieldAccessCast() && (type=sym -> owner -> TypeCast())) {
  4400.         // TypeSymbol * expression_type = expression-> Type();
  4401.         // here if field 
  4402.         if (sym -> ACC_STATIC()) {
  4403.             PutOp(OP_GETSTATIC);
  4404.             ChangeStack(this_control.IsDoubleWordType(type) ? 2: 1);
  4405.         }
  4406.         else {
  4407.             AstFieldAccess *field = expression -> FieldAccessCast();
  4408.             if (field){
  4409.                 EmitExpression(field -> base);
  4410.             }
  4411.             else if (expression -> SimpleNameCast()) {
  4412.                 PutOp(OP_ALOAD_0); // get address of "this"
  4413.             }
  4414.             else {
  4415.                 chaos("LoadReference unexpected base type");
  4416.             }
  4417.             PutOp(OP_GETFIELD);
  4418.             ChangeStack(this_control.IsDoubleWordType(type) ? 1: 0);
  4419.         }
  4420.         PutU2(GenerateFieldReference(sym));
  4421.     }
  4422.     else { // must have expression, the value of which is reference
  4423.       EmitExpression(expression);
  4424.     }
  4425. }
  4426.  
  4427. int  ByteCode::LoadArrayElement(TypeSymbol * type)
  4428. {
  4429.     int opc;
  4430.     if (type == this_control.byte_type
  4431.         || type == this_control.boolean_type) opc=OP_BALOAD;
  4432.     else if (type == this_control.short_type)    opc = OP_SALOAD;
  4433.     else if (type == this_control.int_type)  opc = OP_IALOAD;
  4434.     else if (type == this_control.long_type)  opc = OP_LALOAD;
  4435.     else if (type == this_control.char_type)  opc = OP_CALOAD;
  4436.     else if (type == this_control.float_type)  opc = OP_FALOAD;
  4437.     else if (type == this_control.double_type)  opc = OP_DALOAD;
  4438.     else        opc = OP_AALOAD; // assume reference
  4439.     PutOp(opc);
  4440.     return GetTypeWords(type);
  4441. }
  4442.  
  4443. void ByteCode::StoreArrayElement(TypeSymbol * type)
  4444. {
  4445.     int opc;
  4446.     if (type == this_control.byte_type
  4447.         || type == this_control.boolean_type) opc=OP_BASTORE;
  4448.     else if (type == this_control.short_type)    opc = OP_SASTORE;
  4449.     else if (type == this_control.int_type)  opc = OP_IASTORE;
  4450.     else if (type == this_control.long_type)  opc = OP_LASTORE;
  4451.     else if (type == this_control.char_type)  opc = OP_CASTORE;
  4452.     else if (type == this_control.float_type)  opc = OP_FASTORE;
  4453.     else if (type == this_control.double_type)  opc = OP_DASTORE;
  4454.     else        opc = OP_AASTORE; // assume reference
  4455.     PutOp(opc);
  4456. }
  4457.  
  4458.  
  4459. //  Method to generate field reference
  4460. void ByteCode::StoreField(AstExpression *expression) 
  4461. {
  4462.     // DOT
  4463.     VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
  4464.     TypeSymbol * type = (TypeSymbol *) sym -> owner;
  4465.     TypeSymbol * expression_type=expression-> Type();
  4466.     if (sym -> ACC_STATIC()) {
  4467.         PutOp(OP_PUTSTATIC);
  4468.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
  4469.     }
  4470.     else {
  4471.         PutOp(OP_PUTFIELD);
  4472.         ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
  4473.     }
  4474.     PutU2(GenerateFieldReference(sym));
  4475. }
  4476.  
  4477. void ByteCode::StoreLocalVariable(VariableSymbol * var)
  4478. {
  4479.     StoreLocal(var -> LocalVariableIndex(), var-> Type());
  4480.     if (this_control.option.g && var -> LocalVariableIndex() > last_parameter_index) {
  4481.         if (var -> local_program_counter == 0) {
  4482.             // here to update point of first assignment, marking point at which value is
  4483.             // available to be displayed by debugger.
  4484.             var -> local_program_counter = code_attribute -> code.Length();
  4485.         }
  4486.     }
  4487. }
  4488.  
  4489. void ByteCode::StoreLocal(int varno, TypeSymbol * type)
  4490. {
  4491.     int opc0, opc;
  4492.     if (this_control.IsSimpleIntegerValueType(type)|| type == this_control.boolean_type) {
  4493.         opc0 = OP_ISTORE_0; opc = OP_ISTORE;
  4494.     }
  4495.     else if (type == this_control.long_type) {
  4496.         opc0 = OP_LSTORE_0; opc = OP_LSTORE;
  4497.     }
  4498.     else if (type == this_control.float_type) {
  4499.         opc0 = OP_FSTORE_0; opc = OP_FSTORE;
  4500.     }
  4501.     else if (type == this_control.double_type) {
  4502.         opc0 = OP_DSTORE_0; opc = OP_DSTORE;
  4503.     }
  4504.     else { // assume reference
  4505.         opc0 = OP_ASTORE_0; opc = OP_ASTORE;
  4506.     }
  4507.     if (varno<=3) PutOp(opc0+varno);
  4508.     else if (varno<256) {
  4509.         PutOp(opc); PutU1(varno);
  4510.     }
  4511.     else {
  4512.         PutOp(OP_WIDE); PutOp(opc); PutU2(varno);
  4513.     }
  4514. }
  4515.  
  4516.  
  4517. int ByteCode::GenerateFieldReference(VariableSymbol * sym)
  4518. {
  4519.     // generate a field reg from symbol and class literal
  4520.     // build field ref for field
  4521.     // the field ref requires Utf8 entries for the containing
  4522.     // class, the field name and the field signature, the latter
  4523.     // two expressed as a NameAndTypeEntry
  4524.     if (sym -> constant_pool_index == 0 || sym -> constant_pool_class != class_id) {
  4525.         TypeSymbol * owner = (TypeSymbol *) sym -> owner;
  4526.         sym -> constant_pool_index = BuildFieldref(
  4527.             RegisterClass(owner -> fully_qualified_name),
  4528.             BuildNameAndType(
  4529.                               RegisterUtf8(sym -> ExternalIdentity()-> Utf8_literal),
  4530.                               RegisterUtf8(sym-> Type() -> signature)));
  4531.         sym -> constant_pool_class = class_id;
  4532.     }
  4533.     return sym -> constant_pool_index;
  4534. }
  4535.  
  4536.  
  4537. void ByteCode::StoreSimple (int kind,AstExpression *p)
  4538. {
  4539.     VariableSymbol * sym = (VariableSymbol *) p -> symbol;
  4540.     TypeSymbol * type = (TypeSymbol *) sym -> owner;
  4541.     TypeSymbol * expression_type = p-> Type();
  4542.     switch (kind) {
  4543.         case LHS_LOCAL:
  4544.             StoreLocalVariable(sym);
  4545.             break;
  4546.         case LHS_FIELD:
  4547.         case LHS_STATIC:
  4548.         {
  4549.             if (sym -> ACC_STATIC()) {
  4550.                 PutOp(OP_PUTSTATIC);
  4551.                 ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
  4552.             }
  4553.             else {
  4554.                 PutOp(OP_ALOAD_0); // get address of "this"
  4555.                 PutOp(OP_PUTFIELD);
  4556.                 ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
  4557.             }
  4558.             PutU2(GenerateFieldReference(sym));
  4559.             break;
  4560.             default: chaos("StoreSimple bad kind");
  4561.         }
  4562.     }
  4563. }
  4564.  
  4565. //  Methods to locate and build entries in constant pool.
  4566. u2 ByteCode::BuildDouble(IEEEdouble d)
  4567. {
  4568.     CONSTANT_Double_info *p = new CONSTANT_Double_info(CONSTANT_Double);
  4569.  
  4570.     p -> high_bytes = d.HighWord();             
  4571.     p -> low_bytes = d.LowWord();               
  4572.     constant_pool.Next() = p;
  4573.     constant_pool.Next() = 0; // extra slop for double-word entry
  4574.     return constant_pool.Length()-2;
  4575. }
  4576.  
  4577.  
  4578. u2 ByteCode::BuildFieldref(u2 cl_index, u2 nt_index)
  4579. {
  4580.     CONSTANT_Fieldref_info *p = new CONSTANT_Fieldref_info(CONSTANT_Fieldref);
  4581.  
  4582.     p -> class_index = cl_index;
  4583.     p -> name_and_type_index = nt_index;
  4584.     constant_pool.Next() = p;
  4585.     return constant_pool.Length()-1;
  4586. }
  4587.  
  4588. u2 ByteCode::BuildFloat(IEEEfloat val)
  4589. {
  4590.     CONSTANT_Float_info *p = new CONSTANT_Float_info(CONSTANT_Float);
  4591.     p -> bytes = val.Word();
  4592.     constant_pool.Next() = p;
  4593.     return constant_pool.Length()-1;
  4594. }
  4595.  
  4596. u2 ByteCode::BuildInteger(int val)
  4597. {
  4598.     CONSTANT_Integer_info *p = new CONSTANT_Integer_info(CONSTANT_Integer);
  4599.     p -> bytes =    ((val>>24 & 0xff) << 24) | ((val>>16 & 0xff) << 16)
  4600.                   | ((val>>8 & 0xff) )<< 8 | (val&0xff);
  4601.     constant_pool.Next() = p;
  4602.     return constant_pool.Length()-1;
  4603. }
  4604.  
  4605. u2 ByteCode::BuildInterfaceMethodref(u2 cl_index, u2 nt_index)
  4606. {
  4607.     CONSTANT_InterfaceMethodref_info *p = new CONSTANT_InterfaceMethodref_info(CONSTANT_InterfaceMethodref);
  4608.  
  4609.     p -> class_index = cl_index;
  4610.     p -> name_and_type_index = nt_index;
  4611.     constant_pool.Next() = p;
  4612.     return constant_pool.Length()-1;
  4613. }
  4614.  
  4615. u2  ByteCode::BuildLong(LongInt  val)
  4616. {
  4617.     CONSTANT_Long_info *p = new CONSTANT_Long_info(CONSTANT_Long);
  4618.  
  4619.     p -> high_bytes = val.HighWord();
  4620.     p -> low_bytes = val.LowWord();
  4621.     constant_pool.Next() = p;
  4622.     constant_pool.Next() = 0; // extra slop for double-word entry
  4623.     return constant_pool.Length()-2;
  4624. }
  4625. static char   registered_methods_data[] = {
  4626. //
  4627. // This comment describes the strings below.
  4628. //
  4629. // "java/lang/Object","clone","()Ljava/lang/Object;",                  // Clone
  4630. // "java/lang/Throwable","getMessage","()Ljava/lang/String;",          // Clone_getMessage
  4631. // "java/lang/InternalError","<init>","(Ljava/lang/String;)V",         // Clone_init
  4632. // "java/lang/StringBuffer","toString","()Ljava/lang/String;",         // StringBuffer_toString
  4633. // "java/lang/StringBuffer","<init>","()V",                            // StringBuffer_init
  4634. // "java/lang/StringBuffer","append","([C)Ljava/lang/StringBuffer;",   // StringBuffer_appendCharArray
  4635. // "java/lang/StringBuffer","append","(C)Ljava/lang/StringBuffer;",    // StringBuffer_appendChar
  4636. // "java/lang/StringBuffer","append","(Z)Ljava/lang/StringBuffer;",    // StringBuffer_appendBoolean
  4637. // "java/lang/StringBuffer","append","(I)Ljava/lang/StringBuffer;",    // StringBuffer_appendInt
  4638. // "java/lang/StringBuffer","append","(J)Ljava/lang/StringBuffer;",    // StringBuffer_appendLong
  4639. // "java/lang/StringBuffer","append","(F)Ljava/lang/StringBuffer;",    // StringBuffer_appendFloat
  4640. // "java/lang/StringBuffer","append","(D)Ljava/lang/StringBuffer;",    // StringBuffer_appendDouble
  4641. // "java/lang/StringBuffer","append","(Ljava/lang/String;)Ljava/lang/StringBuffer;", // StringBuffer_appendString
  4642. // "java/lang/StringBuffer","append","(Ljava/lang/Object;)Ljava/lang/StringBuffer;" // StringBuffer_appendObject
  4643. //
  4644.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_O,U_b,U_j,U_e,U_c,U_t,U_NU,
  4645.    U_c,U_l,U_o,U_n,U_e,U_NU,
  4646.    U_LP,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_O,U_b,U_j,U_e,U_c,U_t,U_SC,U_NU,                  // Clone
  4647.  
  4648.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_T,U_h,U_r,U_o,U_w,U_a,U_b,U_l,U_e,U_NU,
  4649.    U_g,U_e,U_t,U_M,U_e,U_s,U_s,U_a,U_g,U_e,U_NU,
  4650.    U_LP,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_NU,          // Clone_getMessage
  4651.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_I,U_n,U_t,U_e,U_r,U_n,U_a,U_l,U_E,U_r,U_r,U_o,U_r,U_NU,
  4652.    U_LT,U_i,U_n,U_i,U_t,U_GT,U_NU,
  4653.    U_LP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_RP,U_V,U_NU,
  4654.    // Clone_init
  4655.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4656.    U_t,U_o,U_S,U_t,U_r,U_i,U_n,U_g,U_NU,
  4657.    U_LP,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_NU,
  4658.    // StringBuffer_toString
  4659.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4660.    U_LT,U_i,U_n,U_i,U_t,U_GT,U_NU,
  4661.    U_LP,U_RP,U_V,U_NU,
  4662.    // StringBuffer_init
  4663. //"java/lang/StringBuffer",
  4664.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4665. //"append",
  4666. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4667.  
  4668. //"([C)Ljava/lang/StringBuffer;",
  4669. U_LP,U_LB,U_C,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4670. // StringBuffer_appendCharArray
  4671. //"java/lang/StringBuffer",
  4672.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4673. //"append",
  4674. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4675. //"(C)Ljava/lang/StringBuffer;",
  4676. U_LP,U_C,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4677. // StringBuffer_appendChar
  4678. //"java/lang/StringBuffer",
  4679.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4680. //"append",
  4681. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4682. //"(Z)Ljava/lang/StringBuffer;",
  4683. U_LP,U_Z,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4684. // StringBuffer_appendBoolean
  4685. //"java/lang/StringBuffer",
  4686.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4687. //"append",
  4688. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4689. //"(I)Ljava/lang/StringBuffer;",
  4690. U_LP,U_I,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4691. // StringBuffer_appendInt
  4692. //"java/lang/StringBuffer",
  4693.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4694. //"append",
  4695. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4696. //"(J)Ljava/lang/StringBuffer;",
  4697. U_LP,U_J,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4698. // StringBuffer_appendLong
  4699. //"java/lang/StringBuffer",
  4700.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4701. //"append",
  4702. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4703. //"(F)Ljava/lang/StringBuffer;",
  4704. U_LP,U_F,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4705. // StringBuffer_appendFloat
  4706. //"java/lang/StringBuffer",
  4707.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4708. //"append",
  4709. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4710. //"(D)Ljava/lang/StringBuffer;",
  4711. U_LP,U_D,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4712. // StringBuffer_appendDouble
  4713. //"java/lang/StringBuffer",
  4714.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4715. //"append",
  4716. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4717. //"(Ljava/lang/String;)Ljava/lang/StringBuffer;",
  4718. U_LP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
  4719. // StringBuffer_appendString
  4720. //"java/lang/StringBuffer",
  4721.    U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
  4722. //"append",
  4723. U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
  4724. //"(Ljava/lang/Object;)Ljava/lang/StringBuffer;"
  4725. U_LP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_O,U_b,U_j,U_e,U_c,U_t,U_SC,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU
  4726.    // StringBuffer_appendObject
  4727. #ifdef DD
  4728. #endif
  4729.    ,U_a // to mark end of last string
  4730. };
  4731.  
  4732. u2 ByteCode::RegisterMethod(int num)
  4733. {
  4734.     // return index for use in method reference, building an entry if necessary.
  4735.     int pos = num * 3;  // starting index of method descriptor
  4736.     // skip precdeing strings
  4737.     int i=0;
  4738.     char *p1, *p2, *p3, *p4;
  4739.     p1 = ®istered_methods_data[0];
  4740.     for (i=0;i<num;i++) {
  4741.         while (*p1++); // skip first string
  4742.         while (*p1++); // skip second string
  4743.         while (*p1++); // skip third string
  4744.     }
  4745.     p2=p1;
  4746.     while (*p2++); // move p2 to stard of second string
  4747.     p3=p2;
  4748.     while (*p3++); // move p3 to stard of third string
  4749.     p4=p3;
  4750.     while(*p4++); // move past end of third string
  4751.     if (registered_methods[num] == 0) {
  4752.           registered_methods[num] = BuildMethodref(
  4753.                 RegisterClass(p1, p2-p1-1),
  4754.                 BuildNameAndType(
  4755.                     RegisterUtf8(p2, p3-p2-1),
  4756.                     RegisterUtf8(p3, p4-p3-1)));
  4757.  
  4758.     }
  4759.     return registered_methods[num];
  4760. }
  4761. u2 ByteCode::BuildMethodref(u2 cl_index, u2 nt_index)
  4762. {
  4763.     CONSTANT_Methodref_info *p = new CONSTANT_Methodref_info(CONSTANT_Methodref);
  4764.  
  4765.     p -> class_index = cl_index;
  4766.     p -> name_and_type_index = nt_index;
  4767.     constant_pool.Next() = p;
  4768.     return constant_pool.Length()-1;
  4769. }
  4770.  
  4771. u2 ByteCode::BuildNameAndType(u2 name, u2 type)
  4772. {
  4773.     CONSTANT_NameAndType_info *p = new CONSTANT_NameAndType_info(CONSTANT_NameAndType);
  4774.  
  4775.     p -> name_index = name;
  4776.     p -> descriptor_index = type;
  4777.     constant_pool.Next() = p;
  4778.     return constant_pool.Length()-1;
  4779. }
  4780.  
  4781.  
  4782. u2 ByteCode::BuildString(u2 si)
  4783. {
  4784.     CONSTANT_String_info *p = new CONSTANT_String_info(CONSTANT_String);
  4785.  
  4786.     p -> string_index = si;
  4787.     constant_pool.Next() = p;
  4788.     return constant_pool.Length()-1;
  4789. }
  4790.  
  4791. u2 ByteCode::BuildUtf8(char * s,int len)
  4792. {
  4793.     CONSTANT_Utf8_info *p = new CONSTANT_Utf8_info(CONSTANT_Utf8);
  4794.     // build Utf8 from ASCII string (assume no embedded nulls), so just do straight copy
  4795.     p -> bytes = new char[len];
  4796.     // compute number of bytes in Utf8 form
  4797.     for (int i=0;i<len;i++) {
  4798.         p -> bytes[i] = s[i];
  4799.     }
  4800.     p -> length_ = len;
  4801.     constant_pool.Next() = p;
  4802.     return constant_pool.Length()-1;
  4803. }
  4804. u2 ByteCode::RegisterClass(Utf8LiteralValue * lit) {
  4805.     if (lit == (Utf8LiteralValue *) 0) chaos("null argument to RegisterClass");
  4806.     if (lit -> constant_pool_class != class_id) {
  4807.         // kill values assigned in prior class
  4808.         lit -> constant_pool_index_Class = 0;
  4809.         lit -> constant_pool_index_String = 0;
  4810.         lit -> constant_pool_index = 0;
  4811.     }
  4812.     if (lit -> constant_pool_index_Class == 0){
  4813.         CONSTANT_Class_info *ci = new CONSTANT_Class_info(CONSTANT_Class);
  4814.         ci -> name_index = (RegisterUtf8(lit));
  4815.         constant_pool.Next() = ci;
  4816.         lit -> constant_pool_index_Class = constant_pool.Length()-1;
  4817.         lit -> constant_pool_class = class_id;
  4818.     }
  4819.     return lit -> constant_pool_index_Class;
  4820. }
  4821.  
  4822. u2 ByteCode::RegisterClass(char * str, int len) {
  4823.     return RegisterClass(this_control.Utf8_pool.FindOrInsert(str,len));
  4824. }
  4825.  
  4826. u2 ByteCode::RegisterDouble(DoubleLiteralValue * lit) {
  4827.     if (lit == (DoubleLiteralValue *) 0) chaos("null argument to RegisterDouble");
  4828.     if (lit -> constant_pool_index == 0 || lit -> constant_pool_class != class_id){
  4829.         lit -> constant_pool_index = BuildDouble(lit -> value);
  4830.         lit -> constant_pool_class = class_id;
  4831.     }
  4832.     return lit -> constant_pool_index;
  4833. }
  4834.  
  4835. u2 ByteCode::RegisterInteger(IntLiteralValue * lit) {
  4836.     if (lit == (IntLiteralValue *) 0) chaos("null argument to RegisterInteger");
  4837.     if (lit -> constant_pool_index == 0 || lit -> constant_pool_class != class_id){
  4838.         lit -> constant_pool_index = BuildInteger(lit -> value);
  4839.         lit -> constant_pool_class = class_id;
  4840.     }
  4841.     return lit -> constant_pool_index;
  4842. }
  4843.  
  4844. u2 ByteCode::RegisterLong(LongLiteralValue * lit) {
  4845.     if (lit == (LongLiteralValue *) 0) chaos("null argument to RegisterLong");
  4846.     if (lit -> constant_pool_index == 0|| lit -> constant_pool_class != class_id){
  4847.         lit -> constant_pool_index = BuildLong(lit -> value);
  4848.         lit -> constant_pool_class = class_id;
  4849.     }
  4850.     return lit -> constant_pool_index;
  4851. }
  4852. u2 ByteCode::RegisterFloat(FloatLiteralValue * lit) {
  4853.     if (lit == (FloatLiteralValue *) 0) chaos("null argument to RegisterFloat");
  4854.     if (lit -> constant_pool_index == 0 || lit -> constant_pool_class != class_id){
  4855.         lit -> constant_pool_index = BuildFloat(lit -> value);
  4856.         lit -> constant_pool_class = class_id;
  4857.     }
  4858.     return lit -> constant_pool_index;
  4859. }
  4860.  
  4861.  
  4862. u2 ByteCode::RegisterString(Utf8LiteralValue * lit) {
  4863.     if (lit == (Utf8LiteralValue *) 0) chaos("null argument to RegisterString");
  4864.     if (lit -> constant_pool_class != class_id) {
  4865.         // kill values assigned in prior class
  4866.         lit -> constant_pool_index_Class = 0;
  4867.         lit -> constant_pool_index_String = 0;
  4868.         lit -> constant_pool_index = 0;
  4869.     }
  4870.     if (lit -> constant_pool_index_String == 0){
  4871.         lit -> constant_pool_index_String = BuildString(RegisterUtf8(lit));
  4872.     }
  4873.     return lit -> constant_pool_index_String;
  4874. }
  4875.  
  4876. u2 ByteCode::RegisterUtf8(Utf8LiteralValue * lit) {
  4877.     if (lit == (Utf8LiteralValue *) 0) chaos("null argument to RegisterUtf8");
  4878.     if (lit -> constant_pool_class != class_id) {
  4879.         // kill values assigned in prior class
  4880.         lit -> constant_pool_index_Class = 0;
  4881.         lit -> constant_pool_index_String = 0;
  4882.         lit -> constant_pool_index = 0;
  4883.     }
  4884.     if (lit -> constant_pool_index  == 0){
  4885.         lit -> constant_pool_index = BuildUtf8(lit -> value,lit -> length);
  4886.         lit -> constant_pool_class = class_id;
  4887.     }
  4888.     return lit -> constant_pool_index;
  4889. }
  4890.  
  4891. u2 ByteCode::RegisterUtf8(char * str, int len) {
  4892.     return RegisterUtf8(this_control.Utf8_pool.FindOrInsert(str,len));
  4893. }
  4894.  
  4895.  
  4896.  
  4897. //  Methods to write out the byte code
  4898. Deprecated_attribute *  ByteCode::CreateDeprecatedAttribute()
  4899. {
  4900.  
  4901.     Deprecated_attribute * deprecated_attribute;
  4902.     u2 deprecated_attribute_name;
  4903.     u4 deprecated_attribute_length = 0;
  4904.     deprecated_attribute_name = RegisterUtf8(U8S_Deprecated, strlen(U8S_Deprecated));
  4905.     deprecated_attribute =  new Deprecated_attribute(deprecated_attribute_name, deprecated_attribute_length);
  4906.     return deprecated_attribute;
  4907. }
  4908.     
  4909. Synthetic_attribute *  ByteCode::CreateSyntheticAttribute()
  4910. {
  4911.  
  4912.     Synthetic_attribute * synthetic_attribute;
  4913.     u2 synthetic_attribute_name;
  4914.     u4 synthetic_attribute_length = 0;
  4915.     synthetic_attribute_name = RegisterUtf8(U8S_Synthetic, strlen(U8S_Synthetic));
  4916.     synthetic_attribute =  new Synthetic_attribute(synthetic_attribute_name, synthetic_attribute_length);
  4917.     return synthetic_attribute;
  4918. }
  4919.     
  4920. void ByteCode::FinishCode(TypeSymbol * type)
  4921. {
  4922.     // finish off code by writing SourceFile attribute
  4923.     // and InnerClasses attribute (if appropriate)
  4924.     u4 sourcefile_attribute_length = 2;
  4925.     int  file_name_start=0;
  4926.     int delim=-1; // location of last delimiter in file name
  4927.        TypeSymbol * class_type;
  4928.     int i;
  4929.     u2 name;
  4930.     char *file_name = this_semantic.lex_stream -> FileName();
  4931.     int file_name_length = this_semantic.lex_stream -> FileNameLength();
  4932.     for (i = file_name_length; i >= 0; i--)
  4933.     {
  4934.         if (file_name[i] == U_SLASH)
  4935.         {
  4936.             delim = i;
  4937.             break;
  4938.         }
  4939.     }
  4940.     // define Source Attribute
  4941.  
  4942.     if (delim != -1) {
  4943.         file_name_start =  delim+1;
  4944.         file_name_length -= (delim + 1);
  4945.     }
  4946.     name = RegisterUtf8(U8S_Sourcefile, strlen(U8S_Sourcefile));
  4947.     SourceFile_attribute * sourcefile_attribute = 
  4948.         new SourceFile_attribute(name, sourcefile_attribute_length);
  4949.     sourcefile_attribute -> sourcefile_index = 
  4950.                                              BuildUtf8(file_name+file_name_start, file_name_length);
  4951.     attributes.Next() = sourcefile_attribute;
  4952.     if (type==(TypeSymbol *) 0) return; // return if interface type
  4953.     if (type -> IsLocal() || type -> IsNested() || type -> NumNestedTypes() > 0) {
  4954.  
  4955.         // here to generate InnerClasses attribute
  4956.         u4 inner_classes_attribute_length = 0;
  4957.         name = RegisterUtf8(U8S_InnerClasses, strlen(U8S_InnerClasses));
  4958.         inner_classes_attribute =
  4959.             new InnerClasses_attribute(name, inner_classes_attribute_length);
  4960.         inner_classes_attribute -> attribute_name_index = name;
  4961.         Tuple<TypeSymbol *> owners;
  4962.         // need to build chain from this type to its owner all the way to the containing type
  4963.         // and then write that out in reverse order (so containing type comes first),
  4964.         // and then write out an entry for each immediately contained type
  4965.         TypeSymbol * this_type = type;
  4966.         if (this_type != type -> outermost_type) {
  4967.             for (this_type = type;this_type != ((TypeSymbol *) 0)  && this_type  != type -> outermost_type;this_type = this_type -> ContainingType()) {
  4968.                 owners.Next() = this_type;
  4969.             }
  4970.         }
  4971.  
  4972.         for (i = owners.Length();i > 0; i--) {
  4973.             SetInnerAttribute(owners[i - 1]);
  4974.         }
  4975.           
  4976.         for (i = 0; i < type -> NumNestedTypes(); i++) {
  4977.             SetInnerAttribute(type -> NestedType(i));
  4978.         }
  4979.  
  4980.         inner_classes_attribute -> attribute_length = 
  4981.             inner_classes_attribute -> inner_classes.Length() * 8 + 2;
  4982.         attributes.Next() = inner_classes_attribute;
  4983.     }
  4984. }
  4985. void ByteCode::AddLocalVariableTableEntry(u2 start,u2 length,u2 name,u2 descriptor,u2 index)
  4986. {
  4987.     // make entry in local variable table
  4988.             int li = local_variable_table_attribute -> local_variable_table.NextIndex();
  4989.             local_variable_table_attribute -> local_variable_table[li].start_pc = start;
  4990.             local_variable_table_attribute -> local_variable_table[li].length = length;
  4991.             local_variable_table_attribute -> local_variable_table[li].name_index = name;
  4992.             local_variable_table_attribute -> local_variable_table[li].descriptor_index = descriptor;
  4993.             local_variable_table_attribute -> local_variable_table[li].index = index;
  4994. }
  4995.  
  4996. void ByteCode::SetInnerAttribute(TypeSymbol * itype)
  4997. {
  4998.     int i = inner_classes_attribute -> inner_classes.NextIndex();
  4999.     inner_classes_attribute -> inner_classes[i].inner_class_info_index = RegisterClass(itype -> fully_qualified_name);
  5000.     if (itype -> IsLocal()) {
  5001.         inner_classes_attribute -> inner_classes[i].outer_class_info_index = 0;
  5002.     }
  5003.     else {
  5004.         TypeSymbol * otype = itype -> ContainingType();
  5005.         inner_classes_attribute -> inner_classes[i].outer_class_info_index = RegisterClass(otype -> fully_qualified_name);
  5006.     }
  5007.     if (itype -> Anonymous()) {
  5008.         inner_classes_attribute -> inner_classes[i].inner_name_index = 0;
  5009.     }
  5010.     else {
  5011.         inner_classes_attribute -> inner_classes[i].inner_name_index = RegisterUtf8(itype -> name_symbol -> Utf8_literal);
  5012.     }
  5013.     AccessFlags flags;
  5014.     flags.access_flags = itype -> access_flags;
  5015.     inner_classes_attribute -> inner_classes[i].inner_class_access_flags = flags.access_flags;
  5016. }
  5017. //  Methods to insert values into byte code
  5018.  
  5019. void ByteCode::PutI1(i1 i)
  5020. {
  5021.     code_attribute -> code.Next() = i&0xff;
  5022. }
  5023.  
  5024. void ByteCode::PutI2(i2 i)
  5025. {
  5026.     code_attribute -> code.Next() = (i>>8) & 0xff;
  5027.     code_attribute -> code.Next() = i & 0xff;
  5028. }
  5029.  
  5030. void ByteCode::PutU1(u1 u)
  5031. {
  5032.     code_attribute -> code.Next() = u & 0xff;
  5033. }
  5034.  
  5035. void ByteCode::PutU2(u2 u)
  5036. {
  5037.     code_attribute -> code.Next() = (u>>8) & 0xff;
  5038.     code_attribute -> code.Next() = u & 0xff;
  5039. }
  5040.  
  5041. void ByteCode::PutU4(u4 u)
  5042. {
  5043.     code_attribute -> code.Next() = (u>>24) & 0xff;
  5044.     code_attribute -> code.Next() = (u>>16) & 0xff;
  5045.     code_attribute -> code.Next() = (u>>8) & 0xff;
  5046.     code_attribute -> code.Next() = u & 0xff;
  5047. }
  5048.  
  5049. //  stack_effect gives effect on stack of executing an opcode
  5050.  
  5051. static int stack_effect[] =
  5052. {
  5053.     0,  // OP_NOP 
  5054.     1,  // OP_ACONST_NULL 
  5055.     1,  // OP_ICONST_M1 
  5056.     1,  // OP_ICONST_0 
  5057.     1,  // OP_ICONST_1 
  5058.     1,  // OP_ICONST_2 
  5059.     1,  // OP_ICONST_3 
  5060.     1,  // OP_ICONST_4 
  5061.     1,  // OP_ICONST_5 
  5062.     2,  // OP_LCONST_0 
  5063.     2,  // OP_LCONST_1 
  5064.     1,  // OP_FCONST_0 
  5065.     1,  // OP_FCONST_1 
  5066.     1, // OP_FCONST_2 
  5067.     2,  // OP_DCONST_0 
  5068.     2,  // OP_DCONST_1 
  5069.     1,  // OP_BIPUSH 
  5070.     1,  // OP_SIPUSH 
  5071.     1,  // OP_LDC 
  5072.     1,  // OP_LDC_W 
  5073.     2,  // OP_LDC2_W 
  5074.     1,  // OP_ILOAD 
  5075.     2,  // OP_LLOAD 
  5076.     1,  // OP_FLOAD 
  5077.     2,  // OP_DLOAD 
  5078.     1,  // OP_ALOAD 
  5079.     1,  // OP_ILOAD_0 
  5080.     1,  // OP_ILOAD_1 
  5081.     1,  // OP_ILOAD_2 
  5082.     1,  // OP_ILOAD_3 
  5083.     2,  // OP_LLOAD_0 
  5084.     2,  // OP_LLOAD_1 
  5085.     2,  // OP_LLOAD_2 
  5086.     2,  // OP_LLOAD_3 
  5087.     1,  // OP_FLOAD_0 
  5088.     1,  // OP_FLOAD_1 
  5089.     1,  // OP_FLOAD_2 
  5090.     1,  // OP_FLOAD_3 
  5091.     2,  // OP_DLOAD_0 
  5092.     2,  // OP_DLOAD_1 
  5093.     2,  // OP_DLOAD_2 
  5094.     2,  // OP_DLOAD_3 
  5095.     1,  // OP_ALOAD_0 
  5096.     1,  // OP_ALOAD_1 
  5097.     1,  // OP_ALOAD_2 
  5098.     1,  // OP_ALOAD_3 
  5099.     -1,  // OP_IALOAD 
  5100.     0,  // OP_LALOAD 
  5101.     -1,  // OP_FALOAD 
  5102.     0,  // OP_DALOAD 
  5103.     -1,  // OP_AALOAD 
  5104.     -1,  // OP_BALOAD 
  5105.     -1,  // OP_CALOAD 
  5106.     -1,  // OP_SALOAD 
  5107.     -1, // OP_ISTORE 
  5108.     -2,  // OP_LSTORE 
  5109.     -1, // OP_FSTORE 
  5110.     -2,  // OP_DSTORE 
  5111.     -1,  // OP_ASTORE 
  5112.     -1,  // OP_ISTORE_0 
  5113.     -1,  // OP_ISTORE_1 
  5114.     -1,  // OP_ISTORE_2 
  5115.     -1,  // OP_ISTORE_3 
  5116.     -2,  // OP_LSTORE_0 
  5117.     -2,  // OP_LSTORE_1 
  5118.     -2,  // OP_LSTORE_2 
  5119.     -2,  // OP_LSTORE_3 
  5120.     -1,  // OP_FSTORE_0 
  5121.     -1,  // OP_FSTORE_1 
  5122.     -1,  // OP_FSTORE_2 
  5123.     -1,  // OP_FSTORE_3 
  5124.     -2,  // OP_DSTORE_0 
  5125.     -2,  // OP_DSTORE_1 
  5126.     -2,  // OP_DSTORE_2 
  5127.     -2,  // OP_DSTORE_3 
  5128.     -1,  // OP_ASTORE_0 
  5129.     -1,  // OP_ASTORE_1 
  5130.     -1,  // OP_ASTORE_2 
  5131.     -1,  // OP_ASTORE_3 
  5132.     -3,  // OP_IASTORE 
  5133.     -4,  // OP_LASTORE 
  5134.     -3,  // OP_FASTORE 
  5135.     -4,  // OP_DASTORE 
  5136.     -3,  // OP_AASTORE 
  5137.     -3,  // OP_BASTORE 
  5138.     -3,  // OP_CASTORE 
  5139.     -3,  // OP_SASTORE 
  5140.     -1,  // OP_POP 
  5141.     -2,  // OP_POP2 
  5142.     1,  // OP_DUP 
  5143.     1,  // OP_DUP_X1 
  5144.     1,  // OP_DUP_X2 
  5145.     2,  // OP_DUP2 
  5146.     2,  // OP_DUP2_X1 
  5147.     2,  // OP_DUP2_X2 
  5148.     0,  // OP_SWAP 
  5149.     -1,  // OP_IADD 
  5150.     -2,  // OP_LADD 
  5151.     -1,  // OP_FADD 
  5152.     -2,  // OP_DADD 
  5153.     -1,  // OP_ISUB 
  5154.     -2,  // OP_LSUB 
  5155.     -1,  // OP_FSUB 
  5156.     -2,  // OP_DSUB 
  5157.     -1,  // OP_IMUL 
  5158.     -2,  // OP_LMUL 
  5159.     -1,  // OP_FMUL 
  5160.     -2,  // OP_DMUL 
  5161.     -1,  // OP_IDIV 
  5162.     -2,  // OP_LDIV 
  5163.     -1,  // OP_FDIV 
  5164.     -2,  // OP_DDIV 
  5165.     -1,  // OP_IREM 
  5166.     -2,  // OP_LREM 
  5167.     -1,  // OP_FREM 
  5168.     -2,  // OP_DREM 
  5169.     0,  // OP_INEG 
  5170.     0,  // OP_LNEG 
  5171.     0,  // OP_FNEG 
  5172.     0,  // OP_DNEG 
  5173.     -1,  // OP_ISHL 
  5174.     -1,  // OP_LSHL 
  5175.     -1,  // OP_ISHR 
  5176.     -1,  // OP_LSHR 
  5177.     -1,  // OP_IUSHR 
  5178.     -1,  // OP_LUSHR 
  5179.     -1,  // OP_IAND 
  5180.     -2,  // OP_LAND 
  5181.     -1,  // OP_IOR 
  5182.     -2,  // OP_LOR 
  5183.     -1,  // OP_IXOR 
  5184.     -2,  // OP_LXOR 
  5185.     0,  // OP_IINC 
  5186.     1,  // OP_I2L 
  5187.     0,  // OP_I2F 
  5188.     1,  // OP_I2D 
  5189.     -1,  // OP_L2I 
  5190.     -1,  // OP_L2F 
  5191.     0,  // OP_L2D 
  5192.     0,  // OP_F2I 
  5193.     1,  // OP_F2L 
  5194.     1,  // OP_F2D 
  5195.     -1,  // OP_D2I 
  5196.     0,  // OP_D2L 
  5197.     -1,  // OP_D2F 
  5198.     0,  // OP_I2B 
  5199.     0,  // OP_I2C 
  5200.     0,  // OP_I2S 
  5201.     -3,  // OP_LCMP 
  5202.     -1,  // OP_FCMPL 
  5203.     -1,  // OP_FCMPG 
  5204.     -3,  // OP_DCMPL 
  5205.     -3,  // OP_DCMPG 
  5206.     -1,  // OP_IFEQ 
  5207.     -1,  // OP_IFNE 
  5208.     -1,  // OP_IFLT 
  5209.     -1,  // OP_IFGE 
  5210.     -1,  // OP_IFGT 
  5211.     -1,  // OP_IFLE 
  5212.     -2,  // OP_IF_ICMPEQ 
  5213.     -2,  // OP_IF_ICMPNE 
  5214.     -2,  // OP_IF_ICMPLT 
  5215.     -2,  // OP_IF_ICMPGE 
  5216.     -2,  // OP_IF_ICMPGT 
  5217.     -2,  // OP_IF_ICMPLE 
  5218.     -2,  // OP_IF_ACMPEQ 
  5219.     -2,  // OP_IF_ACMPNE 
  5220.     0,  // OP_GOTO 
  5221.     1,  // OP_JSR 
  5222.     0,  // OP_RET 
  5223.     -1,  // OP_TABLESWITCH 
  5224.     -1,  // OP_LOOKUPSWITCH 
  5225.     -1,  // OP_IRETURN 
  5226.     -2,  // OP_LRETURN 
  5227.     -1,  // OP_FRETURN 
  5228.     -2,  // OP_DRETURN 
  5229.     -1,  // OP_ARETURN 
  5230.     0,  // OP_RETURN 
  5231.     0,  // OP_GETSTATIC, caller must adjust if long or double
  5232.     0,  // OP_PUTSTATIC, caller must adjust if long or double
  5233.     0,  // OP_GETFIELD, caller must adjust if long or double
  5234.     0,  // OP_PUTFIELD, caller must adjust if long or double
  5235.     -1,  // OP_INVOKEVIRTUAL,   actually  -1-args_length
  5236.     -1,  // OP_INVOKENONVIRTUAL,    actually  -1-args_length
  5237.     0,  // OP_INVOKESTATIC, actually -args_length
  5238.     -1,  // OP_INVOKEINTERFACE, actually -1 -args_length
  5239.     0,  // OP_XXXUNUSEDXXX 
  5240.     1,  // OP_NEW 
  5241.     0,  // OP_NEWARRAY 
  5242.     0,  // OP_ANEWARRAY 
  5243.     0,  // OP_ARRAYLENGTH 
  5244.     0,  // OP_ATHROW 
  5245.     0,  // OP_CHECKCAST 
  5246.     0,  // OP_INSTANCEOF 
  5247.     -1,  // OP_MONITORENTER 
  5248.     -1,  // OP_MONITOREXIT 
  5249.     0,  // OP_WIDE 
  5250.     0,  // OP_MULTIANEWARRAY, actually dims-1
  5251.     -1,  // OP_IFNULL 
  5252.     -1,  // OP_IFNONNULL 
  5253.     0,  // OP_GOTO_W 
  5254.     1,  // OP_JSR_W 
  5255.     0,  // OP_SOFTWARE 
  5256.     0  // OP_HARDWARE
  5257. };
  5258.  
  5259. void ByteCode::PutNop(int optional)
  5260. {
  5261.     // emit NOP. The NOP can be replaced by the next instruction if 
  5262.     // optional is set; otherwise it must be kept.
  5263.     PutOp(OP_NOP);
  5264. // this optimization is causing more trouble than it's worth.
  5265. // latest problem (27 jan 97) was reported by Derek, in that
  5266. // nop just before label definition, resulted in operation generated
  5267. // after label def. being moved before the def! Since it's such a sin
  5268. // to generate junk code, disable the "nop" optimization.
  5269. //  if (optional) last_op_nop = 1;
  5270. }
  5271.  
  5272. void ByteCode::PutOp(unsigned char opc)
  5273. {
  5274. #ifdef TEST
  5275.     int len = code_attribute -> code.Length(); // show current position
  5276.     if (this_control.option.debug_trap_op >0 && code_attribute -> code.Length() == this_control.option.debug_trap_op) {
  5277.         op_trap();
  5278.     }
  5279.     // debug trick - force branch on opcode to see what opcode we are compiling
  5280.     switch (opc) {
  5281.         case OP_NOP: break;
  5282.         case OP_ACONST_NULL: break;
  5283.         case OP_ICONST_M1: break;
  5284.         case OP_ICONST_0: break;
  5285.         case OP_ICONST_1: break;
  5286.         case OP_ICONST_2: break;
  5287.         case OP_ICONST_3: break;
  5288.         case OP_ICONST_4: break;
  5289.         case OP_ICONST_5: break;
  5290.         case OP_LCONST_0: break;
  5291.         case OP_LCONST_1: break;
  5292.         case OP_FCONST_0: break;
  5293.         case OP_FCONST_1: break;
  5294.         case OP_FCONST_2: break;
  5295.         case OP_DCONST_0: break;
  5296.         case OP_DCONST_1: break;
  5297.         case OP_BIPUSH: break;
  5298.         case OP_SIPUSH: break;
  5299.         case OP_LDC: break;
  5300.         case OP_LDC_W: break;
  5301.         case OP_LDC2_W: break;
  5302.         case OP_ILOAD: break;
  5303.         case OP_LLOAD: break;
  5304.         case OP_FLOAD: break;
  5305.         case OP_DLOAD: break;
  5306.         case OP_ALOAD: break;
  5307.         case OP_ILOAD_0: break;
  5308.         case OP_ILOAD_1: break;
  5309.         case OP_ILOAD_2: break;
  5310.         case OP_ILOAD_3: break;
  5311.         case OP_LLOAD_0: break;
  5312.         case OP_LLOAD_1: break;
  5313.         case OP_LLOAD_2: break;
  5314.         case OP_LLOAD_3: break;
  5315.         case OP_FLOAD_0: break;
  5316.         case OP_FLOAD_1: break;
  5317.         case OP_FLOAD_2: break;
  5318.         case OP_FLOAD_3: break;
  5319.         case OP_DLOAD_0: break;
  5320.         case OP_DLOAD_1: break;
  5321.         case OP_DLOAD_2: break;
  5322.         case OP_DLOAD_3: break;
  5323.         case OP_ALOAD_0: break;
  5324.         case OP_ALOAD_1: break;
  5325.         case OP_ALOAD_2: break;
  5326.         case OP_ALOAD_3: break;
  5327.         case OP_IALOAD: break;
  5328.         case OP_LALOAD: break;
  5329.         case OP_FALOAD: break;
  5330.         case OP_DALOAD: break;
  5331.         case OP_AALOAD: break;
  5332.         case OP_BALOAD: break;
  5333.         case OP_CALOAD: break;
  5334.         case OP_SALOAD: break;
  5335.         case OP_ISTORE: break;
  5336.         case OP_LSTORE: break;
  5337.         case OP_FSTORE: break;
  5338.         case OP_DSTORE: break;
  5339.         case OP_ASTORE: break;
  5340.         case OP_ISTORE_0: break;
  5341.         case OP_ISTORE_1: break;
  5342.         case OP_ISTORE_2: break;
  5343.         case OP_ISTORE_3: break;
  5344.         case OP_LSTORE_0: break;
  5345.         case OP_LSTORE_1: break;
  5346.         case OP_LSTORE_2: break;
  5347.         case OP_LSTORE_3: break;
  5348.         case OP_FSTORE_0: break;
  5349.         case OP_FSTORE_1: break;
  5350.         case OP_FSTORE_2: break;
  5351.         case OP_FSTORE_3: break;
  5352.         case OP_DSTORE_0: break;
  5353.         case OP_DSTORE_1: break;
  5354.         case OP_DSTORE_2: break;
  5355.         case OP_DSTORE_3: break;
  5356.         case OP_ASTORE_0: break;
  5357.         case OP_ASTORE_1: break;
  5358.         case OP_ASTORE_2: break;
  5359.         case OP_ASTORE_3: break;
  5360.         case OP_IASTORE: break;
  5361.         case OP_LASTORE: break;
  5362.         case OP_FASTORE: break;
  5363.         case OP_DASTORE: break;
  5364.         case OP_AASTORE: break;
  5365.         case OP_BASTORE: break;
  5366.         case OP_CASTORE: break;
  5367.         case OP_SASTORE: break;
  5368.         case OP_POP: break;
  5369.         case OP_POP2: break;
  5370.         case OP_DUP: break;
  5371.         case OP_DUP_X1: break;
  5372.         case OP_DUP_X2: break;
  5373.         case OP_DUP2: break;
  5374.         case OP_DUP2_X1: break;
  5375.         case OP_DUP2_X2: break;
  5376.         case OP_SWAP: break;
  5377.         case OP_IADD: break;
  5378.         case OP_LADD: break;
  5379.         case OP_FADD: break;
  5380.         case OP_DADD: break;
  5381.         case OP_ISUB: break;
  5382.         case OP_LSUB: break;
  5383.         case OP_FSUB: break;
  5384.         case OP_DSUB: break;
  5385.         case OP_IMUL: break;
  5386.         case OP_LMUL: break;
  5387.         case OP_FMUL: break;
  5388.         case OP_DMUL: break;
  5389.         case OP_IDIV: break;
  5390.         case OP_LDIV: break;
  5391.         case OP_FDIV: break;
  5392.         case OP_DDIV: break;
  5393.         case OP_IREM: break;
  5394.         case OP_LREM: break;
  5395.         case OP_FREM: break;
  5396.         case OP_DREM: break;
  5397.         case OP_INEG: break;
  5398.         case OP_LNEG: break;
  5399.         case OP_FNEG: break;
  5400.         case OP_DNEG: break;
  5401.         case OP_ISHL: break;
  5402.         case OP_LSHL: break;
  5403.         case OP_ISHR: break;
  5404.         case OP_LSHR: break;
  5405.         case OP_IUSHR: break;
  5406.         case OP_LUSHR: break;
  5407.         case OP_IAND: break;
  5408.         case OP_LAND: break;
  5409.         case OP_IOR: break;
  5410.         case OP_LOR: break;
  5411.         case OP_IXOR: break;
  5412.         case OP_LXOR: break;
  5413.         case OP_IINC: break;
  5414.         case OP_I2L: break;
  5415.         case OP_I2F: break;
  5416.         case OP_I2D: break;
  5417.         case OP_L2I: break;
  5418.         case OP_L2F: break;
  5419.         case OP_L2D: break;
  5420.         case OP_F2I: break;
  5421.         case OP_F2L: break;
  5422.         case OP_F2D: break;
  5423.         case OP_D2I: break;
  5424.         case OP_D2L: break;
  5425.         case OP_D2F: break;
  5426.         case OP_I2B: break;
  5427.         case OP_I2C: break;
  5428.         case OP_I2S: break;
  5429.         case OP_LCMP: break;
  5430.         case OP_FCMPL: break;
  5431.         case OP_FCMPG: break;
  5432.         case OP_DCMPL: break;
  5433.         case OP_DCMPG: break;
  5434.         case OP_IFEQ: break;
  5435.         case OP_IFNE: break;
  5436.         case OP_IFLT: break;
  5437.         case OP_IFGE: break;
  5438.         case OP_IFGT: break;
  5439.         case OP_IFLE: break;
  5440.         case OP_IF_ICMPEQ: break;
  5441.         case OP_IF_ICMPNE: break;
  5442.         case OP_IF_ICMPLT: break;
  5443.         case OP_IF_ICMPGE: break;
  5444.         case OP_IF_ICMPGT: break;
  5445.         case OP_IF_ICMPLE: break;
  5446.         case OP_IF_ACMPEQ: break;
  5447.         case OP_IF_ACMPNE: break;
  5448.         case OP_GOTO: break;
  5449.         case OP_JSR: break;
  5450.         case OP_RET: break;
  5451.         case OP_TABLESWITCH: break;
  5452.         case OP_LOOKUPSWITCH: break;
  5453.         case OP_IRETURN: break;
  5454.         case OP_LRETURN: break;
  5455.         case OP_FRETURN: break;
  5456.         case OP_DRETURN: break;
  5457.         case OP_ARETURN: break;
  5458.         case OP_RETURN: break;
  5459.         case OP_GETSTATIC: break;
  5460.         case OP_PUTSTATIC: break;
  5461.         case OP_GETFIELD: break;
  5462.         case OP_PUTFIELD: break;
  5463.         case OP_INVOKEVIRTUAL: break;
  5464.         case OP_INVOKENONVIRTUAL: break;
  5465.         case OP_INVOKESTATIC: break;
  5466.         case OP_INVOKEINTERFACE: break;
  5467.         case OP_XXXUNUSEDXXX: break;
  5468.         case OP_NEW: break;
  5469.         case OP_NEWARRAY: break;
  5470.         case OP_ANEWARRAY: break;
  5471.         case OP_ARRAYLENGTH: break;
  5472.         case OP_ATHROW: break;
  5473.         case OP_CHECKCAST: break;
  5474.         case OP_INSTANCEOF: break;
  5475.         case OP_MONITORENTER: break;
  5476.         case OP_MONITOREXIT: break;
  5477.         case OP_WIDE: break;
  5478.         case OP_MULTIANEWARRAY: break;
  5479.         case OP_IFNULL: break;
  5480.         case OP_IFNONNULL: break;
  5481.         case OP_GOTO_W: break;
  5482.         case OP_JSR_W: break;
  5483.         case OP_SOFTWARE: break;
  5484.         case OP_HARDWARE: break;
  5485.     }
  5486. #endif
  5487.     last_op_pc = code_attribute -> code.Length(); // save pc at start of operation
  5488. #ifdef NOP_OPT
  5489. // this optimization doesn't work - disable for now
  5490. //  if (last_op_nop) {
  5491. //      last_op_nop = 0;
  5492. //      code_attribute -> code[last_op_pc - 1] =  opc;
  5493. //  }
  5494. //  else {
  5495. //      code_attribute -> code.Next() =  opc;
  5496. //  }
  5497. #else
  5498.         code_attribute -> code.Next() =  opc;
  5499. #endif
  5500.     ChangeStack(stack_effect[opc]);
  5501. }
  5502. void ByteCode::ChangeStack(int i)
  5503. {
  5504.     stack_depth += i;
  5505.     if (stack_depth < 0) stack_depth = 0;
  5506.     if (i>0 && stack_depth > code_attribute -> max_stack) {
  5507.         code_attribute -> max_stack = stack_depth;
  5508.     }
  5509. #ifdef TRACE_STACK_CHANGE
  5510.     cout << "stack change: pc " << last_op_pc << " change " << i <<
  5511.             "  stack_depth " << stack_depth << "  max_stack: "<< code_attribute -> max_stack << "\n";
  5512. #endif
  5513. }
  5514.  
  5515. #ifdef TEST
  5516. void ByteCode::PrintCode()
  5517. {
  5518.     int i;
  5519.     cout << "magic " << hex << magic << dec
  5520.             << " major_version " << major_version
  5521.             << " minor_version " << minor_version << "\n";
  5522.     AccessFlags::Print();
  5523.     cout << "\n";
  5524.     cout << " this_class " << this_class << "  super_class " << super_class <<"\n";
  5525.     cout << " constant_pool: " << constant_pool.Length() << "\n";
  5526.     for (i=1;i<constant_pool.Length();i++) {
  5527.         cout << "  " << i << "  ";
  5528.         constant_pool[i] -> print(constant_pool);
  5529.         if (constant_pool[i] -> tag == CONSTANT_Long ||
  5530.             constant_pool[i] -> tag == CONSTANT_Double) {
  5531.             i++;; // skip the next entry for eight-byte constants
  5532.         }
  5533.     }
  5534.     cout << "  interfaces " << interfaces.Length() <<": ";
  5535.     for (i=0;i<interfaces.Length();i++) cout << "  " << (int) interfaces[i];
  5536.     cout <<"\n";
  5537.     for (i=0;i<fields.Length();i++) {
  5538.         cout << "field " << i << "\n";
  5539.         fields[i].print(constant_pool);
  5540.     }
  5541.     cout << " methods length " << methods.Length() << "\n";
  5542.     for (i=0;i<methods.Length();i++) {
  5543.         cout << "method " << i << "\n";
  5544.         methods[i].print(constant_pool);
  5545.     }
  5546.     for (i=0;i<attributes.Length();i++) {
  5547.         cout << "attribute " << i << "\n";
  5548.         attributes[i] -> print(constant_pool);
  5549.     }
  5550.     cout << "\n";
  5551. #endif
  5552.